2

如果我释放链表的头节点,它会只是删除头节点而其他节点仍在内存中,还是会释放整个列表以及如何释放?

4

4 回答 4

5

您的链接列表应如下所示:

head
+---+    +---+    +---+                               
| 1 |--->| 2 |--->| 3 |---+
+---+    +---+    +---+   |                                
                         null  

headnode 只保留第一个节点的地址,如果你这样做free(head),那么它将释放第一个节点的内存1 只有值,其他节点仍然在内存中并且可以访问它们,但是你应该首先保存节点的地址2,以访问链接列表(否则您的代码中会出现内存泄漏)。

喜欢:

   new_head = head->next;
   free(head);

一旦你释放/释放()一个内存,它的未定义行为访问它(地址变得无效)。

来自评论:

  1. 是的,您需要一个循环来为链表中的所有节点释放()内存,请执行以下操作:

     while(head){          // while head not null
         new_head = head->next;   // first save address of next
         free(head);           // free first node
         head = new_head;      // set head to next node, not yet free
     }
    
  2. 注释 2:
    如果您不在程序中删除/释放动态分配的内存,那么它将一直分配给您的进程,直到它不终止(请记住,在 C 中我们没有垃圾收集器)。动态分配的内存在您的程序没有终止之前一直存在。因此,如果您已使用分配的内存完成工作,请明确释放它。
于 2013-07-24T05:54:13.417 回答
1

释放头节点只会释放分配给头节点的内存。其他列表节点将被保留。然后,您必须将头指向列表的下一个成员。例如考虑以下单链表,

A -> B -> C -> D -> 空

释放头节点 A 并将头移动到节点 B 后,链表将如下所示

B -> C -> D -> 空

于 2013-07-24T05:53:20.043 回答
1

释放列表的头节点只会释放该节点,而不是列表的其余部分。

这是数组和链表的主要区别——内存是分开的。这是一个插图:

 struct testnode {
      int a;
      int b;
      struct testnode * next;
 };

在数组中,内存可能如下所示:

 struct testnode test[3];

 0x............0000    &test[0] // on a typical computer
 0x............0020    &test[1]
 0x............0040    &test[2]

请注意数组中的元素是如何彼此相邻布置的?释放测试将释放随后的连续内存,只需一次调用即可释放所有内存。

在链表中,内存可能如下所示:

 struct testnode * head;

 // after insertions

 0x............0000    head
 0x............634f    head->next 
 0x............114d    head->next->next

请注意内存是如何未排序的(尽管它可能并不总是无序的)。并且释放head只会释放head节点,而其余的内存保持不变。

于 2013-07-24T06:03:22.860 回答
0

不,当你释放链表的头节点时,你只将它使用的内存标记为“免费使用”。因此,内存中的其他节点仍将被标记为“正在使用”。

从技术上讲,您仍然可以使用已释放的内存,但这是未定义的行为,因此无法保证数据(包括指针)仍然可以正确使用。

如果要从内存中删除所有节点,则应递归执行(从next指针的角度来看)。

于 2013-07-24T06:36:20.820 回答