C语言链表删除calloc创建的节点时如何避免内存泄漏问题
核心问题说明
你的代码存在两处核心错误:
deleteElement匹配逻辑错误:当前通过data值匹配删除节点,既不符合入参为节点指针的API设计预期,也会导致存在重复data时删错节点,且删除尾节点时未更新链表的tail指针,会产生野指针。- 测试用例6内存泄漏根因:你在main中手动通过
calloc申请了存储'g'的节点传入deleteElement,当函数判断该节点不在链表中时直接返回,没有释放该节点的内存,导致泄漏。
修复方案
方案1(推荐,修改deleteElement逻辑,适配所有测试用例)
直接修正deleteElement的匹配逻辑和内存释放逻辑:
void deleteElement(LinkedList_t *list, LinkedListElement_t *element) { // 空指针无需处理 if (element == NULL) { return; } // 链表为空时直接释放传入的节点 if (list->head == NULL) { free(element); return; } LinkedListElement_t *curr = list->head; LinkedListElement_t *prev = NULL; // 匹配节点指针地址而非data值 while (curr != NULL && curr != element) { prev = curr; curr = curr->next; } if (curr != NULL) { // 节点在链表中,先摘除再释放 if (prev == NULL) { // 摘除头节点 list->head = curr->next; if (list->head == NULL) { list->tail = NULL; } } else { prev->next = curr->next; // 摘除的是尾节点时更新tail if (curr == list->tail) { list->tail = prev; } } free(curr); } else { // 节点不在链表中,直接释放传入的节点 free(element); } }
该方案的优势是完全符合接口封装逻辑,调用方无需关心传入的节点是否在链表中,函数统一负责内存释放,所有测试用例可直接通过。
方案2(不修改接口,仅修改测试用例6代码)
如果你希望保留原接口逻辑,仅解决测试用例6的泄漏问题,可在测试用例6的deleteElement(&alist, element);调用后补充释放逻辑:
deleteElement(&alist, element); // 补充释放外部申请的节点 free(element);
该方案仅适用于临时修复,不推荐作为通用解法,原接口的匹配逻辑缺陷仍然存在。
内容的提问来源于stack exchange,提问作者Annie
相关产品推荐
相关产品推荐

