假设我写,
char **p;
p[0] = strdup("hello");
Strdup在堆中创建一个重复的字符串,其结尾字符为"\0";由于p是char的指针,所以p[0]=strdup("你好"(对我来说似乎很好。但为什么我会出现分段错误呢。
让我们来看一个更简单的例子。假设你说
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]
是有效的。
另请参阅另一个问题的答案,了解有关尝试使用未初始化指针的更多讨论。
声明了一个未初始化的指针,该指针的值不确定。
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
的调用返回的值分配。。