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

C语言如何避免fread函数意外修改其他字符串变量的值

问题根本原因

这是典型的C语言字符串缓冲区未预留空终止符空间导致的未定义行为,栈上的内存溢出和空终止符丢失直接导致了firstNameAux的值看起来被意外修改,具体逻辑如下:

  • 你定义的firstNameAux长度是11,输入的Viniciusopa本身就有11个可见字符,scanf读入字符串时会自动在末尾追加\0作为字符串终止符,这时候\0会溢出到firstNameAux数组边界外的相邻内存,刚好这块内存属于registro数组的起始位置。
  • 执行fread时会把registro的20个字节全部用文件内容覆盖,之前存在registro[0]位置的\0被替换成了文件里的普通字符。
  • 后续打印firstNameAux时,printf读取字符串需要遇到\0才会停止,由于firstNameAux本身没有存储终止符,会一直往后读取栈上的内存内容,所以输出里会带上registro里的内容,看起来就像是firstNameAux被修改了。

修复方案

按以下步骤修改代码即可解决问题:

  1. 扩容字符串数组,预留空终止符位置,长度需要比最大可存储的可见字符数多1:
// 原定义
// char firstNameAux[11];
// char firstName[11];
// char posicao[9];
// 修改为
char firstNameAux[12]; // 最多存11个可见字符+1个\0
char firstName[12];
char posicao[10]; // 最多存9个可见字符+1个\0
  1. 限制scanf输入长度,避免主动溢出:
// 原写法
// scanf("%s", firstNameAux);
// 修改为,最多读取11个字符,自动留1位存\0
scanf("%11s", firstNameAux);
  1. 手动给拷贝后的字符串加空终止符,避免strcmp、printf等函数越界访问内存:
for(int i=0;i<11;i++){
    firstName[i] = registro[i];
}
firstName[11] = '\0'; // 加终止符
for(int i=0;i<9;i++){
    posicao[i] = registro[i+11];
}
posicao[9] = '\0'; // 加终止符
  1. 调整循环判断顺序,避免访问无效内容:如果fread返回0(读到文件末尾/读失败),registro里的内容是无效的,不需要再比较字符串:
// 原写法
// }while(strcmp(firstNameAux, firstName) != 0 && continua);
// 修改为
}while(continua && strcmp(firstNameAux, firstName) != 0);
  1. 可选优化:增加文件指针判空逻辑,避免文件打开失败时程序崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:57:03