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

调试问题:双向链表指针链接异常原因排查

问题根源:数组越界写入破坏了prev指针

你的链表链接问题完全是数组越界写入导致的内存破坏,具体分析如下:

1. 越界写入的触发点

在main函数的文件读取循环中,这段代码存在明显的内存访问错误:

size_t noBytesRead = fread(tmp->text, sizeof(char), CAPACITY, pFile);
tmp->text[noBytesRead] = '\0';

你定义的CAPACITY是128,blob结构体的text数组大小也为128个字符。数组下标从0开始,所以text的有效索引范围是0~127。当fread刚好读取128字节(即noBytesRead == CAPACITY)时,tmp->text[noBytesRead]等价于tmp->text[128]——这已经超出了数组的合法边界,属于非法内存写入。

2. 为什么会破坏prev指针

C语言中结构体成员是按声明顺序连续存储的,你的blob结构体内存布局大致是:

struct blob {
    char text[CAPACITY];  // 占用128字节
    struct blob* prev;    // 紧跟在text数组之后(通常4/8字节,取决于平台)
    struct blob* next;
};

向text[128]写入'\0'时,这个字节会直接覆盖prev指针的部分或全部内存,篡改了prev的地址值,导致它无法正确指向前一个节点,最终出现链接异常。

3. 为什么直接调用insertAtTail的场景没问题

在那个测试场景中,你没有对text数组进行任何写入操作,自然不会触发越界写入,prev指针的内存没有被破坏,链表链接也就正常。

修复方案

最安全的修复方式是调整fread的读取长度,预留一个字节给字符串终止符:

// 最多读取CAPACITY-1个字节,留位置存'\0'
size_t noBytesRead = fread(tmp->text, sizeof(char), CAPACITY - 1, pFile);
tmp->text[noBytesRead] = '\0';

这样无论读取多少字节,tmp->text[noBytesRead]都不会超出数组边界,从根源上避免了内存破坏。

另外补充一个小建议:feof的判断逻辑可以优化——feof只有在尝试读取超出文件末尾后才会被置位,更稳妥的写法是先执行读取操作,再根据读取结果判断是否到达文件末尾或读取失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 19:22:44