我试图遍历链接列表并释放该列表中的所有节点。
该功能可以做到:
它应该释放与堆栈中链表中每个节点相关的空间,但不应释放与内存中的堆栈结构相关的空间,而应将头指针设置为NULL。
这些是我的结构:
typedef struct nodeT {
valueT value;
struct nodeT* next;
} node;
typedef struct {
node* head;
} stack;
这是我遇到的问题:
void ClearStack(stack* s) {
while ( s ) {
node* temp = s->head->next;
free(temp);
}
free(s);
}
在s
内有7个节点。该程序在第二个循环中崩溃,我无法弄清楚出了什么问题。
答案 0 :(得分:2)
您要释放head->next
中的s
,然后将其用于下一个循环NULL
。您应该重新排列顺序:
void ClearStack(stack* s) {
while ( s->head ) {
node* temp = s->head;
s->head = temp->next;
free(temp);
}
free(s);
}
编辑:while
条件修复的说明:当s
内部的所有节点都空闲时,而不是s
本身空闲时,循环应该完成执行。至于循环内的更改,您将磁头存储在temp中,将新磁头设置为head->next
节点,然后释放temp
。这样,列表总是从最前面缩短,并且在head->next
为空时将结束。
答案 1 :(得分:2)
让我们逐步了解代码的作用。假设我们从以下列表开始:
a = { .value = 42, .next = &b }
b = { .value = 0, .next = NULL }
lst = { .head = &a };
我们假设a在内存0x8000上,b在内存0x8008上,lst在内存0x8010上,只是为了获取指针的一些具体值。现在我们称为ClearStack(&lst)。
while (s) # s is 0x8010, so this is true
node *temp = s->head->next; # temp is now 0x8008 (&b).
free(temp); # We free the memory. temp is still 0x8008, but you don't
# own that memory anymore.
while (s) # back to the top of the loop. s is still 0x8010. still true.
node *temp = s->head->next; # temp is assigned to 0x8008 (&b) again.
free(temp); # You already freed that memory; freeing memory you don't
# own is undefined. The program is likely to crash here (*)
您永远不会更改s或s-> head,因此该程序会反复遍历列表中的第一个元素,直到崩溃为止。
(*)尽管不必崩溃;未定义的行为意味着它可以做任何事情,包括像您期望的那样工作一段时间,只是弄乱了头。