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

使用fseeko64在EOF后寻址写入未创建稀疏文件空洞的问题

问题根因

你使用的文件打开标识包含a(append追加模式),这是导致写入被强制顺序追加、无法生成文件空洞的直接原因。

根据C标准库的强制行为定义:只要以带a的模式打开文件,无论之前通过fseeko64把文件指针设置到哪个位置,所有fwrite写操作都会被强制定位到文件的实际末尾执行。

为什么调试排查时找不到问题

你在断点中看到偏移量计算正确、fseeko64返回值为0,是因为fseeko64确实修改了FILE结构体内部记录的逻辑偏移值。但进入实际写入环节时,stdio库会偷偷把这个偏移值重置为当前文件的真实长度,再执行写入操作。
对应你的最小复现代码流程:

  • 第一次打开文件写入data块,文件长度从0增长为40字节(10个uint32的总大小)
  • 第二次打开文件依然用了"ar+b"模式,你手动把偏移设置为900,但执行fwrite时,偏移被自动重置到40字节的位置,直接把data2块追加在第一块后面
  • 最后你从900偏移位置读取时,读到的是从未被写入的未分配磁盘块(也就是本该生成空洞的区域),自然和预期存在900位置的data2内容不匹配

这也完全解释了你用十六进制转储看到的现象:两个数据块完全顺序拼接,中间根本没有留出空隙。

修正方案

所有写操作场景下,直接去掉打开模式里的a标识即可。如果需要兼容“文件不存在时自动创建、存在时不截断原有内容”的需求,按如下逻辑处理:

// 先尝试以可读写、不截断原有内容的模式打开
FILE* file = fopen64(fn.c_str(), "r+b");
if (file == nullptr) {
    // 文件不存在时,以可读写、创建新文件的模式打开
    file = fopen64(fn.c_str(), "w+b");
}

补充说明:append模式的设计目标是支持多进程并发写同一个日志文件时,避免写入覆盖、内容错位,它天生不支持随机按偏移写入的场景,完全不适合存储稀疏结构数据。

内容的提问来源于stack exchange,提问作者T.Aoukar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 05:06:04