You need to enable JavaScript to run this app. 添加Note节点删除功能后,选择case3时触发segmentation fault (core dumped)报错
优惠活动
大模型
产品
解决方案
定价
更多

添加Note节点删除功能后,选择case3时触发segmentation fault (core dumped)报错

链表删除功能触发段错误的定位与修复方案

第一步:快速定位崩溃位置

  • 带调试信息编译代码:gcc -g your_code.c -o demo,关闭编译优化以匹配源码行号
  • 用gdb运行程序复现case3的操作,段错误触发后输入bt查看栈回溯,可直接定位到deleteNote函数内的无效内存访问行
  • 也可通过valgrind做内存检查:valgrind --tool=memcheck ./demo,工具会直接报出访问非法内存的具体代码位置、触发场景

核心崩溃根因

代码在删除逻辑里存在多处无效内存访问的漏洞,也是段错误的直接来源:

  1. 找匹配节点的内层循环退出时,没有区分退出原因:循环退出要么是找到了值为x的节点,要么是遍历完整条链表走到了t == NULL的末尾。原代码没有判断t是否为NULL,直接执行prev->next = t->next,对NULL指针解引用,直接触发段错误——最常见的触发场景就是要删除的x值在链表中根本不存在。
  2. prev变量未初始化,是栈上的随机野指针:当遍历过程中第一个碰到的节点就是匹配值x时,prev从未被赋值,后续对prev->next的写操作会直接往随机内存地址写入数据,触发崩溃。
  3. 最开始判断链表为空的分支没有加return,打印完提示后会继续执行后续遍历逻辑,逻辑上存在隐患。
  4. 外层循环的流程逻辑冗余,没有在链表遍历到末尾时及时退出循环,会持续触发无效访问。

修复后的可运行代码

void deleteNote(int x){
    Note *t = head;
    Note *prev = NULL; // 初始化prev,避免野指针

    // 链表为空时直接返回,不执行后续逻辑
    if(head == NULL){
        printf("List already empty.\n");
        return;
    }

    // 先处理链表头部连续匹配的节点
    while(t != NULL && t->data == x){
        head = t->next;
        free(t);
        number--; // 维护全局节点计数
        t = head;
        printf("Note %d deleted.\n", x);
    }

    // 头部节点全部删完后链表已空,直接返回
    if(t == NULL){
        return;
    }

    // 遍历剩余节点完成匹配删除
    while(t != NULL){
        if(t->data == x){
            // 找到匹配节点,执行删除
            prev->next = t->next;
            free(t);
            number--;
            t = prev->next;
            continue;
        }
        // 节点不匹配,同步移动prev和t指针
        prev = t;
        t = t->next;
    }
}

验证注意事项

  • 覆盖所有边界测试场景:链表为空时触发删除、要删除的x值不存在、x值是链表最后一个节点、x值是链表头部连续多个节点,确保所有场景下不会触发非法内存访问
  • 每次free节点后,及时将遍历指针指向新的后继节点,避免使用已释放的野指针

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.10 09:15:03