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

删除100及以上数值时程序报heap use after free错误如何解决

错误原因分析

  • 核心触发原因:delete函数删除尾节点时未更新全局tail指针。当你删除的节点正好是链表最后一个节点(current == tail)时,仅修改了前驱节点的next指针、释放了原尾节点的内存,但全局tail仍然指向已经被释放的内存地址。后续调用insert执行tail->next = newNode时,就会访问已释放的堆内存,触发Heap use after free错误。
  • 为什么仅删除100及以上数值时触发:通常这类场景下数值是按从小到大顺序插入链表,较大的数值默认处于链表尾部,因此删除大数值时命中尾节点删除的逻辑才会触发问题,删除小数值(非尾节点)时不会影响tail指针的合法性。
  • 附带的隐性问题:
    1. insert函数先执行malloc申请内存,再校验重复值,若校验到重复直接返回,会导致刚申请的newNode内存泄漏。
    2. delete函数未做空链表校验,若链表为空时调用删除,直接访问head->data会触发空指针崩溃。

修复方案

1. 修正delete函数的尾指针更新逻辑

删除节点时增加尾节点判断,同时补充空链表校验,修改后代码:

void delete(int n){
    // 补充空链表判断
    if(head == NULL) return;
    if(head->data == n){
        struct Node *tempHead = head;
        head = head->next;
        free(tempHead);
        // 删完头节点后链表为空,同步将tail置为NULL
        if(head == NULL) tail = NULL;
        return;
    } else{
        struct Node *current = head;
        struct Node *prev = NULL;
        while(current!=NULL && current->data!=n){
            prev = current;
            current = current->next;
        }
        if(current==NULL) return;
        
        prev->next = current->next;
        // 如果删除的是尾节点,更新tail为前驱节点
        if(current == tail) {
            tail = prev;
        }
        free(current);
    }
}

2. 修正insert函数的内存泄漏问题

将重复校验提前到内存申请之前,同时补充内存申请失败的容错处理:

void insert(int nData) {
    // 先校验重复,无重复再申请内存
    if(checkDuplicates(nData)==1){
        return;
    }
    struct Node *newNode = (struct Node*)malloc(sizeof(struct Node)+10);
    // 补充malloc失败校验,避免空指针操作
    if(newNode == NULL) return;
    
    newNode->data = nData;
    newNode->next = NULL;
    if(head == NULL){
        head = newNode;
        tail = newNode;
    }
    else {  
        tail->next = newNode;  
        tail = newNode;  
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:15:03