The issue you are having is a little more fundamental to your use of pointers and what happens when you pass a pointer as an argument to a function. When you pass a pointer to a function (just like any variable), the function receives a copy of that pointer (or variable). Meaning that when header is passed to myFunc, myFunc receives a copy of header as data (with its very own, and very different, address):
#include <stdio.h>
#include <stdlib.h>
void myFunc(char **data);
int main() {
char **header;
printf ("\n the address of header in main: %p\n", &header);
myFunc(header);
printf("[In main] %s\n", header[1]); // This gives segmentation fault
return 0;
}
void myFunc(char **data) {
data = malloc(2 * sizeof(char *));
printf ("\n the address of data in myFunc: %p\n", &data);
data[0] = "test";
data[1] = "test 2";
printf("[In myFunc] %s\n", data[1]); // This works just fine
}
Output
$ ./bin/myFunc1
the address of header in main: 0x7ffd112e27b8
the address of data in myFunc: 0x7ffd112e2798
[In myFunc] test 2
Segmentation fault
Note: how the address of header in in main is 0x7ffd112e27b8, but when you allocate memory for data in myFunc, you are assigning the starting address for the new block of memory to a pointer at 0x7ffd112e2798. Nothing in main knows anything about memory address 0x7ffd112e2798.
How Do We Fix it?
Just like you do every other time you wish to pass a variable to a function, update that variable, and have the changed value reflected back in the calling function (main here) -- you pass the address of that variable to the function:
#include <stdio.h>
#include <stdlib.h>
void myFunc(char ***data);
int main() {
char **header;
printf ("\n the address of header in main: %p\n", &header);
myFunc(&header); /* passing address of header to myFunc */
printf("[In main] %s\n", header[1]);
return 0;
}
void myFunc(char ***data) {
*data = malloc(2 * sizeof(char *));
printf ("\n the address of data in myFunc: %p\n", data);
(*data)[0] = "test";
(*data)[1] = "test 2";
printf("[In myFunc] %s\n", (*data)[1]);
}
Now that you have passed the address of header to myFunc as data, when you allocate memory for *data, you are allocating memory and returning the pointer to the same address for header in main. Which allows:
Output
$ ./bin/myFunc2
the address of header in main: 0x7ffdd72b1968
the address of data in myFunc: 0x7ffdd72b1968
[In myFunc] test 2
[In main] test 2
Making Use of the Return from myFunc
You can also return the starting address for the new block of memory to main and accomplish the same thing, e.g.:
#include <stdio.h>
#include <stdlib.h>
char **myFunc(char **data);
int main() {
char **header;
printf ("\n the address of header in main: %p\n", &header);
header = myFunc(header);
printf("[In main] %s\n", header[1]); // This works fine too
return 0;
}
char **myFunc(char **data) {
data = malloc(2 * sizeof(char *));
printf ("\n the address of data in myFunc: %p\n", &data);
data[0] = "test";
data[1] = "test 2";
printf("[In myFunc] %s\n", data[1]); // This works just fine
return data;
}
Output
$ ./bin/myFunc3
the address of header in main: 0x7ffee22e3298
the address of data in myFunc: 0x7ffee22e3278
[In myFunc] test 2
[In main] test 2
Now main knows about the address allocated to data in myFunc by virtue of assigning the return to header.
char **header;to `char **header = NULL;malloc(), 1) do not cast the returned value as it is avoid*so can be assigned to any other pointer. Casting just clutter the code and adds headaches to debugging and maintenance of the code. 2) before using the returned value, always check (!=NULL) to assure the operation was successful.data[0] = "test";needs to be:(*data)[0] = "test";This line:myFunc(header);passes the contents ofheaderwhat needs to be passed is the address of header:myFunc( &header );data = (char **)malloc(2 * sizeof(char *));is not setting the contents ofheaderto point to the malloc'd area. it should be:*data = malloc(2 * sizeof(char *));And, of course, check *data for !=NULL before actually using the pointer