使用字符数组和 strdup,获取分段错误

问题描述

假设我写,

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

Strdup 在堆中创建一个重复的字符串,结尾字符为“\0”;由于 p 是指向 char 指针的指针,因此 p[0] = strdup("hello") 对我来说似乎非常好。但是为什么我会遇到分段错误

解决方法

让我们看一个更简单的例子。假设你说

int *ip;
ip[0] = 5;

ip 是一个指向一个或多个 int 的指针——但它没有被初始化,所以它没有指向任何地方,所以 ip[0] 不是一个有效的内存位置,所以我们可以不要在那里存储值 5。

同样的,当你说

char **p;

p 是一个无处指向的指针。如果它确实指向某个地方,它将指向另一个指针。但它没有指向任何地方,所以

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

爆炸。

要解决这个问题,您需要使 p 指向某处,特别是分配给一个或多个指针的内存。有很多方法可以做到这一点:

char *q;
p = &q;                                 /* way 1 */

char *a[10];
p = a;                                  /* way 2 */

p = malloc(10 * sizeof(char *));        /* way 3 */

或者不使用指针,而是使用数组开头:

char *p[10];                            /* way 4 */

在其中任何一个之后,p[0] = strdup("hello") 应该可以工作。

对于方式 3,我们还需要检查 malloc 是否成功(它不返回空指针)。

对于方法 2 到 4,我们还可以设置 p[1]p[9]。但对于方式 1,只有 p[0] 有效。

有关尝试使用未初始化指针的更多讨论,另请参阅 this answerdifferent question

,

声明了一个具有不确定值的未初始​​化指针。

char **p;

因此取消引用此语句中使用的此表达式p[0](相当于表达式*p)中的指针

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

调用未定义的行为,因为尝试使用表达式 p[0] 的错误指针值写入内存。

你可以写一个例子

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

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

即指向 p 的指针必须指向一个有效的对象。因此,取消引用指针,您将获得类型为 char * 的有效对象,该对象将由 strdup 调用返回的值分配..