Let's look at a simpler example. Suppose you say
int *ip;
ip[0] = 5;
ip
is a pointer to one or more int
s -- but it's not initialized, so it points nowhere, so ip[0]
isn't a valid memory location, so we can't store the value 5 there.
In the same way, when you said
char **p;
p
is a pointer that points nowhere. If it did point somewhere, it would point to another pointer. But it doesn't point anywhere, so
p[0] = strdup("hello");
blows up.
To fix this, you need to make p
point somewhere, and specifically to memory allocated to hold one or more pointers. There are many ways to do this:
char *q;
p = &q; /* way 1 */
char *a[10];
p = a; /* way 2 */
p = malloc(10 * sizeof(char *)); /* way 3 */
or instead of using a pointer, use an array to start with:
char *p[10]; /* way 4 */
After any of those, p[0] = strdup("hello")
should work.
For way 3, we would also need to check that malloc
succeeded (that it dd not return a null pointer).
For ways 2 through 4, we could also set p[1]
through p[9]
. But for way 1, only p[0]
is valid.
See also this answer to a different question for more discussion about trying to use uninitialized pointers.