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

fgets读取字符数超存储数组大小:原代码正常复现却崩溃?

为什么fgets第二个参数超过数组长度会导致程序崩溃?

这是典型的缓冲区溢出触发未定义行为导致的问题,咱们一步步拆解原因:

1. 核心问题:数组空间不足,触发非法内存访问

你定义的str是一个仅能容纳80个字符的栈数组(char str[80];),而fgets的第二个参数表示的是最多写入的字符数(包含末尾的\0终止符)。当你传入200时,fgets会尝试往str所在的内存区域写入最多199个字符加1个终止符,这远远超出了str的80字节容量。

这种越界写入会覆盖栈上str之后的其他数据——比如你的FILE* fi指针变量,或者函数的返回地址。一旦这些关键数据被破坏,程序执行到后续步骤(比如fclose(fi)或者函数返回时)就会访问非法内存,直接崩溃。

2. 为什么原项目能“正常运行”?

这其实是未定义行为的典型表现:未定义行为不代表一定会崩溃,它的结果完全不可预测。可能原项目满足以下某个条件:

  • 编译选项或栈内存布局和你在Eclipse中的环境不同,溢出的区域刚好是未被使用的栈空间,没有破坏关键数据;
  • 项目中读取的file文件里,每行内容都很短(远小于80字符),实际并没有触发真正的溢出;
  • 运气好,溢出的内容刚好没有影响到程序的关键执行流程。

但这绝对不是“正确”的运行,只是侥幸而已——哪天输入内容变长,或者环境变化,原项目一样会崩溃。

3. 正确的修复方式

永远要保证fgets的第二个参数不超过缓冲区的实际大小,最稳妥的方式是用sizeof(str)来自动获取数组长度,这样就算以后修改数组大小也不会出错:

fgets(str, sizeof(str), fi);

另外顺便提一句:你代码里的while(!feof(fi))也是一个常见的坑,它会导致最后一行被重复读取一次,建议改成检查fgets的返回值:

while(fgets(str, sizeof(str), fi) != NULL) {
    // do things
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:30:30