不能直接 mmap vector.data(),因为vector内存由malloc分配,而mmap要求自身管理映射区域,直接调用会失败并返回map_failed;正确做法是先mmap分配内存再用std::span访问。

为什么不能直接 mmap vector.data()?
因为 std::vector 的内存是堆上动态分配的,操作系统无法将用户态 malloc 分配的地址直接映射到文件——mmap 要求映射区域必须由它自己管理(或通过 MAP_ANONYMOUS + MAP_SHARED 配合 msync 模拟)。直接对 vec.data() 调用 mmap 会失败并返回 MAP_FAILED,错误码通常是 EINVAL。
正确做法:用 mmap 分配内存,再构造 vector 的 view
真正可行的路径是:先用 mmap 创建一块可读写、可同步到文件的共享内存区域,然后用该地址构造一个类似 std::span 或裸指针数组的访问接口。C++20 的 std::span 最适合这个场景,避免拷贝、不接管所有权。
- 用
mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0)分配匿名页(仅用于后续msync到文件) - 更推荐:先
open()文件,ftruncate()扩容,再mmap(..., fd, 0)映射文件内容 -
std::vector本身不参与映射——你只需要一个std::span<t></t>指向 mmap 返回的地址,长度等于元素个数 - 记得在退出前调用
msync(addr, len, MS_SYNC)和munmap(addr, len),否则修改可能丢失
示例关键片段:
int fd = open("data.bin", O_RDWR | O_CREAT, 0644);
size_t N = 1000000;
size_t bytes = N * sizeof(double);
ftruncate(fd, bytes);
double* ptr = static_cast<double>(mmap(nullptr, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (ptr == MAP_FAILED) { /* handle error */ }
std::span<double> data_span{ptr, N}; // 安全、零开销访问
// 使用 data_span[i] 读写,等价于 vector[i]
msync(ptr, bytes, MS_SYNC);
munmap(ptr, bytes);
close(fd);
</double></double>
如果非要“把现有 vector 内容映射到文件”,只能拷贝
已有 std::vector<t> vec</t>,想持久化到文件并支持 mmap 访问?没有捷径。必须把数据写入文件(write() 或 memcpy 到 mmap 区域),然后重新 mmap 该文件。不存在“把 vector 的 heap 内存直接变成 mmap 区域”的系统调用。
- 不要尝试
mmap后memcpy到 mmap 地址——可以,但和直接写文件没本质区别,且多一次 memcpy - 若 vector 很大(GB 级),建议分块 mmap + 分块写,避免一次性申请过大虚拟内存
- 注意
sizeof(T)必须是 trivially copyable,否则memcpy或 mmap 二进制 dump 会出错 - 跨平台时,Windows 要用
CreateFileMapping/MapViewOfFile,语义类似但 API 完全不同
常见坑:未对齐访问、大小端、生命周期管理
映射后的内存是 raw 字节流,std::span<t></t> 的类型安全只在 T 的布局一致时成立。实际踩过的坑包括:
-
struct成员有 padding,不同编译器/平台对齐方式不同 → mmap 后读取字段偏移错乱 - 文件在 x86 上生成,拿到 ARM 设备上 mmap 读取整数 → 大小端不匹配,数值全错(需手动
htole32等) - 忘记
munmap导致 fd 泄漏或虚拟内存耗尽;忘记msync导致程序崩溃后文件内容仍是旧值 - 映射时用了
MAP_PRIVATE—— 修改不会写回文件,msync也无效
真正要长期可靠使用 mmap 做 vector 替代,得配套定义明确的二进制协议、对齐约束和同步策略,不是简单换掉 new/delete 就完事。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











