Search code examples
cdereference

c - dereferencing issue


I have simplified an issue that I've been having trying to isolate the problem, but it is not helping.

I have a 2 dimensional char array to represent memory. I want to pass a reference to that simulation of memory to a function. In the function to test the contents of the memory I just want to iterate through the memory and print out the contents on each row.

The program prints out the first row and then I get seg fault.

My program is as follows:

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

#include <string.h>

void test_memory(char*** memory_ref)  {

    int i;
    for(i = 0; i < 3; i++)  {
        printf("%s\n", *memory_ref[i]);
    }
}

int main()  {
    char** memory;
    int i;
    memory = calloc(sizeof(char*), 20);
    for(i = 0; i < 20; i++)  {
        memory[i] = calloc(sizeof(char), 33);
    }

    memory[0] = "Mem 0";
    memory[1] = "Mem 1";
    memory[2] = "Mem 2";

    printf("memory[1] = %s\n", memory[1]);

    test_memory(&memory);

    return 0;
}

This gives me the output:

memory[1] = Mem 1
Mem 0
Segmentation fault

If I change the program and create a local version of the memory in the function by dereferencing the memory_ref, then I get the right output:

So:

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

#include <string.h>

void test_memory(char*** memory_ref)  {

    char** memory = *memory_ref;
    int i;
    for(i = 0; i < 3; i++)  {
        printf("%s\n", memory[i]);
    }
}

int main()  {
    char** memory;
    int i;
    memory = calloc(sizeof(char*), 20);
    for(i = 0; i < 20; i++)  {
        memory[i] = calloc(sizeof(char), 33);
    }

    memory[0] = "Mem 0";
    memory[1] = "Mem 1";
    memory[2] = "Mem 2";

    printf("memory[1] = %s\n", memory[1]);

    test_memory(&memory);

    return 0;
}

gives me the following output:

memory[1] = Mem 1
Mem 0
Mem 1
Mem 2

which is what I want, but making a local version of the memory is useless because I need to be able to change the values of the original memory from the function which I can only do by dereferencing the pointer to the original 2d char array.

I don't understand why I should get a seg fault on the second time round, and I'd be grateful for any advice.

Many thanks

Joe


Solution

  • Try:

    printf("%s\n", (*memory_ref)[i]);
    

    The current version is equivalent to

    *(*(memory_ref + i));
    

    This is because the [] operator has higher precedence than the dereference *. Which means that when i is larger than 0 you try to read memory after the char*** temporary memory_ref

    The second version is equal to (*memory_ref)[i] which means that you will be indexing the correct memory.

    EDIT: The reason it works on the first iteration is because:

    *(*(memory_ref + 0)) == *((*memory_ref) + 0)