程序崩溃因未检查mmap返回值,其失败时返回map_failed而非nullptr,直接使用会触发段错误;常见原因包括fd无效、权限不足、文件大小为0或length为0,须用if(addr==map_failed)判断并perror。

mmap映射大文件时为什么程序直接崩溃?
因为没检查 mmap 返回值。它失败时返回 MAP_FAILED(即 (void*)-1),而不是 nullptr;直接当指针用会触发段错误。
常见诱因:文件描述符无效、权限不足(比如 PROT_READ 但文件只写)、文件大小为 0、或 length 传了 0。
- 务必用
if (addr == MAP_FAILED)判断,再调perror("mmap") - 映射长度不能超过文件实际大小(除非用
MAP_NORESERVE+ftruncate预分配) - Linux 下普通用户默认有
vm.max_map_count限制,超限会静默失败——查dmesg | tail看内核日志
PROT_READ 和 PROT_WRITE 怎么配才安全?
只读映射最稳妥:PROT_READ + MAP_PRIVATE,适合分析型场景(如日志扫描、二进制解析)。写入会触发 SIGBUS,但不会污染原文件。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
要修改文件内容,必须用 PROT_READ | PROT_WRITE + MAP_SHARED,且确保 open 时带 O_RDWR 标志。
-
MAP_PRIVATE写操作触发写时复制(COW),不落盘,适合临时处理 -
MAP_SHARED写操作同步到文件,但需注意:若映射区跨页未对齐,msync可能只刷部分页 - 不要混用
PROT_WRITE和MAP_PRIVATE去“假装”改文件——改了也白改
映射超大文件(>2GB)要注意什么?
32 位程序天然受限:地址空间碎片化,很难找到连续的数百 MB 空闲虚拟内存。64 位下也要防 ENOMEM——不是磁盘满,是内核无法预留足够 VMA 区域。
- 用
lseek(fd, 0, SEEK_END)+ftell精确获取文件大小,避免stat.st_size在某些 NFS 上不准 - 优先映射局部区域(如跳过头部,从偏移
1GB开始映射100MB),用offset参数分块处理 -
offset必须是页对齐的(通常是getpagesize()的整数倍),否则mmap直接失败
munmap 后还能访问内存吗?
不能。一旦调 munmap,对应虚拟地址区间立即失效,再读写就是未定义行为(大概率 SIGSEGV)。但注意:这和文件本身无关——文件仍存在,只是映射关系解除了。
- 别依赖 RAII 自动释放:C++ 没强制要求析构函数调
munmap,必须显式调 - 如果映射后 fork 了子进程,父进程
munmap不影响子进程的映射(VMA 是进程私有) - 频繁映射/解映射大文件会加剧内核 VMA 管理开销,不如长期持有映射,用
madvise(MADV_DONTNEED)主动丢弃不用页
munmap 会清空缓存,其实它只删 VMA,页缓存还在。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










