c-为什么释放内存会导致分段错误



我很绝望,因为这种代码形式有时会给我带来分段错误,我不知道为什么。实际上,它只需要添加一些链表注释,打印它们,然后通过释放内存清空列表。

struct int_list {
int value;
struct int_list *next;
};
typedef struct int_list IntList;

void list_print(IntList *start)
{
IntList *cur = start;
while(cur != NULL)
{
printf("%dn", cur->value);
cur = cur->next;
}
}

void list_append(IntList **start, int newval)
{
IntList *newel = malloc(sizeof(IntList));
newel->value = newval;
newel->next = NULL;
if(*start == NULL)
{
*start = newel;
}
else
{
IntList *cur = *start;
while(cur->next != NULL)
{
cur = cur->next;
}
cur->next = newel;
}
}

void list_free(IntList *start)
{
IntList *prev = start;                           // prev = start
while (start != NULL)                            // if start != Null
{
start = start->next;                         // make start point to the next element
printf("Deleting %dn", prev->value);
free(prev);                                  // delete the previous element
prev = start;                                // make previous point to start again
}
printf("n");
}

int main(int argc, char *argv[])
{
// fill the list
IntList *start = NULL;
list_append(&start, 42);
list_append(&start, 30);
list_append(&start, 16);
// print the list
printf("nList 1n");
list_print(start);
printf("n");
// free the memory and print again
list_free(start);
printf("Empty list:n");
list_print(start);
printf("n");
}

在我尝试实现list_free((之前,一切都很好。因此,我强烈认为错误可以在这个函数中找到。只是发布代码的其余部分,因为我是结构的新手,不能100%确定是否正确处理了它们。你知道我做错了什么吗?。。。

由于悬挂指针,您有未定义的行为

list_free(start);

也就是说,start仍然指向您试图访问的已释放内存。

您需要在freeing后将start设置为NULL

list_free(start);
start = NULL;
printf("Empty list:n");
list_print(start);
函数list_free通过值获取参数。因此,该函数处理指向节点的原始指针的副本。因此,指向节点start的原始指针保持不变。

因此,调用函数list_free后的列表输出

list_free(start);
printf("Empty list:n");
list_print(start);

具有未定义的行为。

函数应该像函数list_append那样通过引用接受指向节点的原始指针。

例如

void list_free( IntList **start )
{
while ( *start != NULL )
{
IntList *prev = *start;                     // prev = start
*start = ( *start )->next;                  // make start point to the next element
printf("Deleting %dn", prev->value);
free(prev);                                  // delete the previous element
}
printf("n");
}

调用类似的函数

list_free( &start );

在退出函数之后,原始指针start将等于NULL。这就是名单将被真正释放的原因。

这比列表的客户端应明确地将指针设置为NULL自己时要好。他可能会犯与您忘记将指针设置为NULL相同的错误。

指针仍然指向已释放内存的内存位置,这也是分段错误的一个实例。它是"未定义的行为",可以导致任意不可预测的事情发生,因为指向位置的内容是未知的,运行时会发生变化。

相关内容

  • 没有找到相关文章

最新更新