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

为何此C函数中出现“fread: EFAULT, bad address”错误?

为啥你的generator函数读大文件会报"fread: Bad address"?

咱们先揪出问题的核心:你的fread调用参数写错了,直接引发了缓冲区溢出,进而触发了内存访问错误。

先看这段出问题的代码:

limit = fread(buffer, sizeof (unsigned int), sizeof buffer, stdin);

搞懂fread的参数逻辑是关键

fread的官方原型是这样的:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

每个参数的作用得理清楚:

  • ptr:用来存数据的缓冲区指针
  • size:单个数据元素的字节大小(比如你的unsigned int的大小)
  • nmemb:要读取的元素个数(不是总字节数!)
  • 返回值:实际成功读取的元素个数

你的错误就出在第三个参数:你传了sizeof buffer,这是整个缓冲区的总字节数,但fread期望这里是缓冲区能装下的unsigned int元素个数。

举个实际场景的例子(假设unsigned int占4字节):

  • 你的buffer定义是unsigned int[8192 / sizeof(unsigned int)],也就是2048个元素,总字节数8192
  • 但你告诉fread要读取8192个unsigned int元素,这需要32768字节的空间——你的缓冲区根本装不下这么多!

缓冲区溢出为啥会导致"Bad address"?

当fread往buffer里写超出它容量的数据时,会直接覆盖缓冲区后面的内存区域。而你的pos和limit都是静态变量,它们的内存位置刚好和buffer紧挨着(静态变量通常存在同一个内存段里)。

这种溢出会带来两个致命问题:

  1. 直接破坏pos和limit的正常数值,导致后续访问buffer数组时出现越界
  2. 严重时会覆盖其他关键内存数据,触发系统的非法内存访问检测,也就是你看到的"Bad address"错误

怎么修复?

把fread的第三个参数改成缓冲区能容纳的元素个数就行——其实你定义buffer的时候已经算过这个值了,直接复用:

// 用缓冲区总字节数除以单个元素大小,得到元素个数
limit = fread(buffer, sizeof(unsigned int), sizeof(buffer)/sizeof(unsigned int), stdin);

或者更通用的写法(不管数组元素类型是什么都能用):

limit = fread(buffer, sizeof(buffer[0]), sizeof(buffer)/sizeof(buffer[0]), stdin);

为啥大文件才触发错误?

小文件可能只需要1-2次读取操作,溢出的内存还没破坏到关键变量,所以暂时没报错;但你的95MiB大文件需要多次填充缓冲区,很快就会把pos、limit甚至其他内存数据搞乱,直接触发内存访问错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 03:43:20