试图清空链表

时间:2019-09-06 20:30:42

标签: c

我试图遍历链接列表并释放该列表中的所有节点。

该功能可以做到:

它应该释放与堆栈中链表中每个节点相关的空间,但不应释放与内存中的堆栈结构相关的空间,而应将头指针设置为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个节点。该程序在第二个循环中崩溃,我无法弄清楚出了什么问题。

2 个答案:

答案 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,因此该程序会反复遍历列表中的第一个元素,直到崩溃为止。

(*)尽管不必崩溃;未定义的行为意味着它可以做任何事情,包括像您期望的那样工作一段时间,只是弄乱了头。