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

使用mmap映射大文件后重启程序读取全为0的问题排查

问题分析与解决

核心问题:fopen的打开模式错误

你使用"w+"模式打开文件,这个模式的行为是:

  • 若文件已存在,会直接将其长度截断为0,彻底清空原有内容
  • 若文件不存在,则创建新文件

所以第二次运行程序时,第一步就把之前写入数据的文件清空了,后续ftruncate只是把空文件扩展到指定大小,自然读取到的全是0。

修正方案

把fopen的模式改成"r+"(读写模式,文件必须存在,不会截断原有内容)。如果需要兼容文件不存在的场景,可以先判断文件是否存在,不存在时用"w+"创建,存在时用"r+"打开:

#include <sys/stat.h>
#include <unistd.h>

int64_t mmbytes = 1 << 36;
FILE* file = nullptr;
struct stat st;

// 判断文件是否存在
if (stat(filename, &st) == 0) {
    // 文件存在,用r+模式打开(读写,不截断)
    file = fopen(filename, "r+");
} else {
    // 文件不存在,创建并打开
    file = fopen(filename, "w+");
}

if (!file) {
    perror("Failed: ");
    throw std::runtime_error(std::strerror(errno));
}

int fd = fileno(file);
// 仅当文件新创建或长度不符合要求时,执行ftruncate
if (stat(filename, &st) != 0 || st.st_size != mmbytes) {
    int r = ftruncate(fd, mmbytes);
    if (r != 0) {
        perror("Failed: ");
        throw std::runtime_error(std::strerror(errno));
    }
}

// 后续mmap代码保持不变
void* mm = mmap(nullptr, mmbytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mm == MAP_FAILED) {
    fprintf(stderr, "mmap error for output, errno %d\n", errno);
    exit(-1);
}

额外注意事项

  • MAP_FILE标志在多数系统中是可选的(MAP_SHARED已隐含文件映射逻辑),可以移除,不影响功能
  • 操作完成后记得调用munmap(mm, mmbytes)释放映射,fclose(file)关闭文件
  • 64GB的大文件操作需确保系统支持(比如文件系统开启大文件特性、内存映射资源充足)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:10:31