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

C语言get_next_line复用同fd重开文件触发SIGABRT排查

问题根因

这个崩溃和read()的行为没有关系,核心是你实现里跨调用缓存剩余内容的静态缓冲区没有处理fd复用的场景:

  • get_next_line一般会用静态指针数组,按文件描述符索引存储每次read()多读出的、属于下一行的残留内容,这部分内存是跨函数调用持久存在的,不会随函数返回自动释放。
  • 当你第一次循环读到文件EOF时,大概率只释放了返回行的内存,或者释放了对应fd的静态缓存但没有把缓存指针置为NULL,留下了野指针。
  • close(fd)是内核态的文件关闭操作,你的用户态get_next_line函数感知不到这个动作,不会主动清理自己维护的静态缓存。当你重新open拿到相同数值的fd时,函数会误把残留的野指针当成这个新fd的有效缓存,传给ft_strjoinfree做字符串拼接,ft_strjoinfree尝试free这个已经被释放的野指针,就会触发glibc的double free校验,发送SIGABRT终止程序。
修复方法

两处修改即可,完全符合单函数不超过25行的课程要求:

  1. 当read()返回0(到达EOF)时,取出最后一行内容返回前,先释放对应fd的静态缓存内存,立刻将该缓存指针置为NULL,不能只free不置空。

    注意:free操作不会修改指针本身的值,free后指针仍然指向之前的堆地址,属于典型野指针,下次访问就会触发内存错误。

  2. 增加错误分支处理:当read()返回值小于0(读操作出错)时,直接释放对应fd的静态缓存、将指针置为NULL后返回NULL,避免错误状态下的内存泄漏和野指针残留。
错误实现参考

如果你处理EOF的逻辑是下面这样,必然会触发这个崩溃:

/* 错误写法:free后没有置空缓存指针 */
if (read_ret == 0) {
    current_line = get_line_from_cache(remain[fd]);
    free(remain[fd]);
    return current_line;
}

修正后的逻辑如下:

/* 正确写法:free后立刻将缓存指针置空 */
if (read_ret == 0) {
    current_line = get_line_from_cache(remain[fd]);
    free(remain[fd]);
    remain[fd] = NULL; // 核心修复,消除野指针
    return current_line;
}
快速验证方式

你可以在第一次读到EOF、get_next_line返回最后一行后,打印对应fd的静态缓存指针值,如果不是NULL,就可以确认是这个问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:42:23