windows下createfilemapping映射结构体数组到文件本质是内存与文件视图绑定,需确保结构体为标准布局、显式对齐,且dwmaximumsizehigh/low设为总大小,映射后须用flushviewoffile同步落盘。

Windows下用CreateFileMapping映射结构体数组到文件
直接映射结构体数组到磁盘文件,本质是把一段内存(含结构体布局)与文件视图绑定,读写内存即读写文件。Windows上必须用 CreateFileMapping + MapViewOfFile,不能只靠 fopen 或 std::ofstream。
关键前提:结构体必须是标准布局(standard-layout),不能有虚函数、非公有非静态数据成员、继承关系;所有成员需显式对齐一致,否则映射后读取会错位。
- 先用
CreateFile打开或创建文件,注意要带GENERIC_READ | GENERIC_WRITE和CREATE_ALWAYS(首次写入)或OPEN_EXISTING(后续复用) -
CreateFileMapping的dwMaximumSizeHigh/dwMaximumSizeLow必须设为结构体数组总大小(sizeof(MyStruct) * N),不能只传单个结构体大小 -
MapViewOfFile返回的指针可直接转成MyStruct*,但必须检查返回值是否为NULL—— 常见错误是文件句柄无效或大小不匹配,此时GetLastError()返回ERROR_INVALID_HANDLE或ERROR_MAPPED_FILE_SIZE_MISMATCH
Linux下用mmap + open实现等效映射
Linux没有“文件映射对象”概念,直接用 mmap 将文件 fd 映射为内存区域。结构体数组映射方式更直接,但也更依赖手动控制。
常见坑是文件大小未预先设置:如果映射前文件长度为 0,mmap 会失败并返回 MAPPED_FAILED,错误码为 EINVAL。必须先用 ftruncate 把文件扩展到目标大小。
- 用
open(..., O_RDWR | O_CREAT)获取 fd,权限掩码别漏掉0644 - 调用
ftruncate(fd, sizeof(MyStruct) * N)确保文件有足够空间 -
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)中MAP_SHARED是必须的 —— 若用MAP_PRIVATE,修改不会写回磁盘 - 映射成功后,指针可安全 reinterpret_cast 为
MyStruct*,但要注意结构体字段字节序和填充(#pragma pack(1)可禁用填充,但需确保跨平台读写一致)
结构体对齐与跨平台写入一致性问题
同一个结构体在不同编译器或平台下,sizeof 可能不同,导致映射后读出字段偏移错乱。这不是映射机制的问题,而是二进制布局不兼容。
- 绝对不要依赖默认对齐 —— 在结构体定义前加
#pragma pack(1)(GCC/Clang/MSVC 都支持),或用alignas和std::byte手动排布 - 避免使用
bool、short等宽度不确定类型;统一用int32_t、uint8_t等固定宽度整型 - 字符串成员不能存裸指针或
std::string—— 它们指向堆内存,映射后失效;应改用定长数组如char name[64],或序列化为紧凑二进制块 - 写入前建议用
static_assert(std::is_standard_layout_v<mystruct>)</mystruct>和static_assert(sizeof(MyStruct) == expected_size)做编译期校验
映射后数据持久性与同步时机
映射本身不等于立即落盘。操作系统会缓存修改,除非主动触发同步,否则断电或崩溃可能导致部分更新丢失。
- Windows 下调用
FlushViewOfFile(ptr, size)强制刷入文件映射视图;若还需保证磁盘物理写入,再调FlushFileBuffers(hFile) - Linux 下用
msync(ptr, size, MS_SYNC)(阻塞直到落盘)或MS_ASYNC(仅提交到内核缓冲区) - 不要依赖进程退出自动保存 ——
UnmapViewOfFile或munmap只解除映射,不保证数据已写完 - 多进程同时映射同一文件时,需自行加锁(如命名互斥量或文件锁),
mmap和CreateFileMapping本身不提供并发保护
真正麻烦的从来不是怎么映射,而是怎么让结构体在十年后、换编译器后、迁移到另一台机器上,还能被正确解读出来。对齐、字节序、字段生命周期,每个都得亲手钉死。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











