You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode 2487代码中delete curr引发heap-use-after-free错误原因排查

解决LeetCode 2487时的堆内存重复释放问题

问题背景

我在解决LeetCode 2487《移除链表中的节点》问题时,采用的C++解法思路是:先反转链表,移除左侧(对应原链表右侧)存在更大值的节点,最后再次反转链表。但代码仅在注释掉delete curr;时能通过所有测试用例;取消注释该行就会触发AddressSanitizer: heap-use-after-free error。

相关代码

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;

        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }

        return prev;
    }

    ListNode* removeNodes(ListNode* head) {
        head = reverseList(head);

        int curMax = INT_MIN;
        ListNode dummy(0);

        dummy.next = head;
        ListNode* prev = &dummy;
        ListNode* curr = head;

        while (curr) {
            if (curr->val < curMax) {
                ListNode* temp = curr->next;
                prev->next = curr->next;
                // delete curr;  // 取消注释该行会崩溃
                curr = temp;

            } else {
                curMax = max(curMax, curr->val);
                prev = curr;
                curr = curr->next;
            }
        }

        return reverseList(dummy.next);;
    }
};

我原本的写法是:

if (curr->val < curMax) {
    prev->next = curr->next;
    delete curr;
    curr = prev->next;
}

错误原因分析

查看错误日志可知,问题出在LeetCode测试框架的__ListNodeUtils__::freeList函数中:

SUMMARY: AddressSanitizer: heap-use-after-free (solution+0x1aa425) in __ListNodeUtils__::freeList(ListNode*&)

本质原因是同一个节点被重复释放:

  • LeetCode的测试框架会负责创建输入链表,并且在你的函数执行完毕后,自动遍历并释放输入链表和输出链表的所有节点内存。
  • 如果你在函数内部手动delete了某些输入链表的节点,测试框架后续尝试再次释放这些节点时,就会触发堆内存重复释放的错误。

解决方法

在LeetCode的题目场景下,不需要手动释放节点内存。你只需要调整链表的指针指向,构建出符合要求的链表结构即可,内存管理完全由测试框架负责。

直接注释掉所有delete相关代码,就能避免和测试框架的内存释放逻辑冲突,同时保证功能正确。

修正后可运行代码

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;

        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }

        return prev;
    }

    ListNode* removeNodes(ListNode* head) {
        head = reverseList(head);

        int curMax = INT_MIN;
        ListNode dummy(0);
        dummy.next = head;
        ListNode* prev = &dummy;
        ListNode* curr = head;

        while (curr) {
            if (curr->val < curMax) {
                ListNode* temp = curr->next;
                prev->next = curr->next;
                curr = temp;
            } else {
                curMax = max(curMax, curr->val);
                prev = curr;
                curr = curr->next;
            }
        }

        return reverseList(dummy.next);
    }
};

内容的提问来源于stack exchange,提问作者notSukuna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:10:05