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

直接将fread()的返回值用作索引为何是不良编程实践?

将fread()的返回值用作索引为何是不良编程实践?

嘿,我最近刚踩过这个坑——写了个读取.meta文件的函数,直接把fread()的返回值当数组索引用,结果被前辈狠狠批了一顿。今天就跟你掰扯掰扯,为啥这是个绝对不能碰的不良编程实践。

首先得搞明白fread()的返回值到底是什么:它返回的是成功读取的元素个数,只有当你指定每个元素大小为1字节时,它才等于读取的字节数。但就算是这种情况,直接拿它当索引用也藏着不少雷:

  • 分不清“正常读完”和“读取出错”
    当fread()返回的数值小于你请求读取的数量时,你根本没法直接判断是“真的读到文件末尾了”,还是“中途磁盘出错、读不下去了”。我之前就是直接用这个返回值给数组加终止符,前辈说:“要是磁盘读一半卡壳,你拿这个半截数据当完整的meta信息用,后面解析全乱套,出问题你都不知道是读取环节出的错!”

  • 类型不匹配容易踩溢出坑
    fread()的返回值是size_t类型,这是个无符号整数。要是你数组的索引习惯用int这种有符号类型,一旦读取的字节数超过int的最大值,类型转换后会变成负数索引,直接触发数组越界访问——这可是程序崩溃、出现诡异行为的常客,查bug能查到你怀疑人生。

  • 隐含的未定义行为风险
    就算你侥幸没遇到错误,看似正常的场景也可能出问题:比如你请求读取META_MAX字节,数组大小是META_MAX+1,刚好fread()返回META_MAX,这时候buffer[META_MAX] = '\0'是安全的,但如果fread()因为某些奇怪的系统问题返回了一个超过数组大小的值(虽然概率低,但不是不可能),直接当索引用就会越界,触发未定义行为。

那正确的姿势应该是啥样的?给你看我后来改的代码逻辑:

char buffer[META_MAX + 1];
size_t bytes_read = fread(buffer, 1, META_MAX, fp);
// 先检查读取状态
if (bytes_read < META_MAX) {
    if (ferror(fp)) {
        // 处理读取错误,比如报错返回
        perror("读取.meta文件失败");
        return -1;
    }
    // 走到这里就是正常读到文件尾了
}
// 确认没问题再给数组加终止符
buffer[bytes_read] = '\0';

先判断读取是否出错,确认没问题再用返回值操作数组,这样就把风险都堵上了。

备注:内容来源于stack exchange,提问作者Mio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:09:37