我有一个函数返回一个多重间接指针作为结果,如下所示:
typedef struct {
int id;
char *name;
} user;
user **myfn(int users_count) {
user **a;
a = malloc(sizeof(user) * user_counts);
for(int i = 0 ; i<user_counts ; i++) {
*(a+i) = malloc(sizeof(user));
(*(a+i))->id = 1;
(*(a+i))->name = malloc(sizeof(char) * 25);
strncpy((*(a+i))->name, "Morteza", 25); // just for example
}
return a;
}
现在,当我想在 main 函数中爬取这个结果时,它会显示所有用户名,但最后会遇到 Segmentation fault
错误。
int main() {
user **a = myfn(10);
int i = 0;
while((*(a+i)) != NULL) {
printf("ID: %d \t %s\n", (*(a+i))->id, (*(a+i))->name);
i++;
}
}
结果:
ID: 1 Morteza
ID: 2 Morteza
...
...
ID: 10 Morteza
Segmentation fault (core dumped)
为什么 while
的 condition
不能正常工作?
最佳答案
首先,
a = malloc(sizeof(user) * user_counts);
有一个问题 - 你想分配 user_counts
个 pointers 实例给 user
,而不是 user
, 所以那一行应该是
a = malloc(sizeof(user *) * user_counts);
但是,有一个更简单的方法来解决这个问题 - sizeof
运算符可以将 expressions 作为参数以及类型名称。所以你可以将该行重写为
a = malloc( sizeof *a * user_counts );
表达式 *a
的类型是user *
,所以sizeof *a
等价于 sizeof(用户 *)
。这让您的生活变得更简单了,因为您不必弄清楚 a
指向的类型 - 让编译器完成艰苦的工作。
您应该始终检查 malloc
调用的结果。
a = malloc( sizeof *a * users_count );
if ( a )
{
// do stuff with a
}
其次,不要使用 *(a+i)
索引到 a
- 请改用 a[i]
。让事情更容易阅读。所以,
*(a+i) = malloc(sizeof(user));
(*(a+i))->id = 1;
(*(a+i))->name = malloc(sizeof(char) * 25);
成为
a[i] = malloc(sizeof *a[i]);
if ( a[i] )
{
a[i]->id = 1;
a[i]->name = malloc(sizeof *a[i]->name * 25);
}
else
{
/* deal with memory allocation failure */
}
现在,针对您的实际问题。您的代码因以下原因之一而崩溃:
a
的初始malloc
失败,因此您在使用a[i]
的第一行崩溃;- 您的
a[i]
之一的malloc
失败,因此您在a[i]->id = 1
上崩溃>; - 您已成功为
a
的所有users_count
元素分配内存 - noa[i]
是NULL
,因此您遍历数组的最后一个元素并尝试取消引用紧随其后的对象,这很可能不是有效指针。
除了在每次 malloc
调用后添加检查之外,您可能还应该根据 users_count
进行循环:
for ( i = 0; i < users_count; i++ )
printf("ID: %d \t %s\n", a[i]->id, a[i]->name);
或者,您需要为a
分配一个额外的元素并将其设置为NULL
:
a = malloc( sizeof *a * (users_count + 1) );
if ( a )
{
a[users_count] = NULL;
for ( i = 0; i < users_count; i++ )
...
}
请注意,calloc
将所有分配的内存初始化为 0,因此您可以使用它而不必担心将元素显式设置为 NULL
:
a = calloc( users_count + 1, sizeof *a );
if ( a )
{
for ( i = 0; i < users_count; i++ )
...
}
关于在 C 中检查 NULL 指针不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41862570/