0

Suppose i write,

char **p;
p[0] = strdup("hello");

Strdup creates a duplicate string in heap with ending character '\0'; As p is pointer to pointer of char, p[0] = strdup("hello") seems perfectly fine for me. But why am i getting segmentation fault.

  • 6
    `p` points nowhere. So `p[0]` is noplace, and you can't store `strdup`'s return value there. – Steve Summit Jul 19 '21 at 14:39
  • Maybe `char **p` -> `char *p[10]`. Or just `char *p; p = strdup(...`, depending on what you're trying to achieve. With `char *p[10]`, `p` is an array of 10 pointers to char, each of them pointing initially nowhere. – Jabberwocky Jul 19 '21 at 14:42

2 Answers2

1

Let's look at a simpler example. Suppose you say

int *ip;
ip[0] = 5;

ip is a pointer to one or more ints -- 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.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
0

There is declared an uninitialized pointer that has an indeterminate value.

char **p;

so dereferencing the pointer in this expression p[0] (that is equivalent to the expression *p) used in this statement

p[0] = strdup("hello");

invokes undefined behavior because there is an attempt to write to memory using an incorrect pointer value of the expression p[0].

You could write either for example

char *s;
char **p = &s;
p[0] = strdup("hello");

Or

char **p = malloc( sizeof( char * ) );
p[0] = strdup("hello");

That is the pointer to pointer p must point to a valid object. Thus dereferencing the pointer you will get a valid object of the type char * that will be assigned by the value returned by the call of strdup..

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335