如何解决在 C 中释放整个链表
我知道这个问题在这个网站上被问了很多,所以我很抱歉再次问这个问题,但我真的被卡住了。我正在尝试创建一个删除整个链表的函数(在 C 中)。任何建议都会真正帮助我。我附上了函数的当前代码、链表结构和 Valgrind 上的结果。
typedef struct node {
void* data;
struct node* next;
} node_t;
typedef struct list {
node_t* head;
int (*comparator)(void*,void*);
void (*printer)(void*);
void (*deleter)(void*);
int length;
} list_t;
void DestroyList(list_t* list) {
if (list == NULL) return;
struct list_t* curr;
while (list != NULL) {
curr = list;
list = list->head->next;
free(curr);
}
}
Valgrind 输出:
[[ Valgrind Errors Detected ]]
==1045== Memcheck,a memory error detector
==1045== copyright (C) 2002-2017,and GNU GPL'd,by Julian Seward et al.
==1045== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1045== Command: ./main
==1045== Parent PID: 16
==1045==
==1045== Use of uninitialised value of size 8
==1045== at 0x109DDC: DestroyList (hw2.c:123)
==1045== by 0x10964F: _genos_unittest (DestroyList_small_list.c:30)
==1045== by 0x109517: main (genos_unittest.h:173)
==1045==
==1045== Invalid read of size 8
==1045== at 0x109DDC: DestroyList (hw2.c:123)
==1045== by 0x10964F: _genos_unittest (DestroyList_small_list.c:30)
==1045== by 0x109517: main (genos_unittest.h:173)
==1045== Address 0x2e2e2e35 is not stack'd,malloc'd or (recently) free'd
==1045==
==1045==
==1045== HEAP SUMMARY:
==1045== in use at exit: 95 bytes in 8 blocks
==1045== total heap usage: 10 allocs,2 frees,151 bytes allocated
==1045==
==1045== 16 bytes in 1 blocks are definitely lost in loss record 6 of 8
==1045== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1045== by 0x1095B0: _genos_unittest (DestroyList_small_list.c:17)
==1045== by 0x109517: main (genos_unittest.h:173)
==1045==
==1045== 16 bytes in 1 blocks are definitely lost in loss record 7 of 8
==1045== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1045== by 0x10975A: InsertAtHead (linkedlist.c:54)
==1045== by 0x109643: _genos_unittest (DestroyList_small_list.c:27)
==1045== by 0x109517: main (genos_unittest.h:173)
==1045==
==1045== 37 (16 direct,21 indirect) bytes in 1 blocks are definitely lost in loss record 8 of 8
==1045== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1045== by 0x10975A: InsertAtHead (linkedlist.c:54)
==1045== by 0x1095A6: _genos_unittest (DestroyList_small_list.c:15)
==1045== by 0x109517: main (genos_unittest.h:173)
==1045==
==1045== LEAK SUMMARY:
==1045== definitely lost: 48 bytes in 3 blocks
==1045== indirectly lost: 21 bytes in 2 blocks
==1045== possibly lost: 0 bytes in 0 blocks
==1045== still reachable: 26 bytes in 3 blocks
==1045== suppressed: 0 bytes in 0 blocks
==1045== Reachable blocks (those to which a pointer was found) are not shown.
==1045== To see them,rerun with: --leak-check=full --show-leak-kinds=all
==1045==
==1045== For counts of detected and suppressed errors,rerun with: -v
==1045== Use --track-origins=yes to see where uninitialised values come from
==1045== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
再次,任何帮助将不胜感激。谢谢!
解决方法
list
的类型为 list_t*
,但 list->head->next
的类型为 struct node*
。您应该使用正确类型的指针来遍历列表。
它会是这样的:
void DestroyList(list_t* list) {
if (list == NULL) return;
node_t* itr = list->head;
node_t* curr;
while (itr != NULL) {
curr = itr;
itr = itr->next;
// if appropriate
// free(curr->data);
free(curr);
}
// if appropriate
// free(list);
}
,
您的 DestroyList()
实现错误(它甚至不应该编译,因为您试图将 struct node*
指针分配给 list_t*
指针)。
试试这个:
void DestroyList(list_t* list) {
if (list == NULL) return;
struct list_t *curr = list->head,*next;
while (curr != NULL) {
next = curr->next;
free(curr);
curr = next;
}
// depending on whether you want the list to be just cleared,// or actually destroyed,you need either:
list->head = NULL;
// or:
free(list);
}
,
对于初学者来说,不清楚结构 data
的数据成员 struct node
是否指向动态分配的对象。
typedef struct node {
void* data;
struct node* next;
} node_t;
通常它应该指向一个动态分配的对象。
其次,struct list
类型的对象可以具有自动存储持续时间。因此,在函数 DestroyList
中,指针 list
不应用于释放 struct list
类型的指向对象。
在该函数中,您需要释放数据成员 data
指向的所有动态分配的节点和其他对象。
调用该函数后,列表应为有效的空列表。
并且每个列表只有一个 struct list
类型的对象。所以例如这些行
struct list_t* curr;
//...
curr = list;
//...
free(curr);
没有意义。
因此可以通过以下方式定义函数
void DestroyList( list_t *list )
{
while ( list->head != NULL )
{
node_t *curr = list->head;
list->head = list->head->next;
free( curr->data );
free( curr );
}
list->length = 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。