createfilemapping读大文件更快因绕过用户态拷贝、减少内核/用户空间搬运;适用于几十mb以上且需随机访问的场景,但小文件或顺序读可能更慢。

为什么CreateFileMapping读大文件比fread快?
因为内存映射不走用户态缓冲区拷贝,绕过多次内核/用户空间数据搬运。当文件大于几十MB、且需随机访问(比如跳着读某几块结构体),CreateFileMapping + MapViewOfFile 的延迟和吞吐优势立刻显现。但注意:它不是“一定更快”——小文件、顺序流式读取反而可能因页表建立开销更慢。
常见误判点:没设对dwMaximumSizeHigh/dwMaximumSizeLow导致映射失败却返回NULL;或用INVALID_HANDLE_VALUE直接传给CreateFileMapping而不检查CreateFile是否真成功。
- 必须用
GENERIC_READ打开文件,不能只用FILE_SHARE_READ -
flProtect = PAGE_READONLY足够读取,别用PAGE_READWRITE徒增页表权限开销 - 文件大小超4GB时,
dwMaximumSizeHigh必须非零,否则高位被截断 → 映射区域变小甚至失败
如何安全映射超4GB文件并避免MapViewOfFile返回NULL?
关键在两处:一是CreateFileMapping的大小参数必须拆成高低32位;二是MapViewOfFile的dwNumberOfBytesToMap不能超过实际文件大小,且需对齐到系统页边界(通常4KB)。
错误示例:MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0) —— 第五个参数为0会尝试映射整个对象,但若文件>2GB且hMap是32位进程创建的,可能触发内部截断。
- 先调
GetFileSizeEx获取真实大小(LARGE_INTEGER),再拆成DWORD高低位传给CreateFileMapping -
MapViewOfFile的dwNumberOfBytesToMap建议显式指定,例如min(100ULL * 1024 * 1024, fileSize),避免隐式全映射风险 - 映射后务必用
IsBadReadPtr(仅调试)或直接访问首字节+GetLastError()判断是否真正可读,Windows不保证MapViewOfFile成功就等于内存立即可用
CreateFileMapping的hFile能传INVALID_HANDLE_VALUE吗?什么场景下必须传真实句柄?
能传,但含义完全不同:INVALID_HANDLE_VALUE创建的是“稀疏”内存映射(即 backing store 在页面提交时才分配物理内存),适合做进程间共享内存或临时大缓冲区;而传真实文件句柄才是“文件映射”,数据持久化且可随机读磁盘内容。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
你如果目标是“读已有磁盘文件”,必须传CreateFile返回的有效句柄,否则映射出来是一片全零内存,跟原文件内容完全无关。
- 传
INVALID_HANDLE_VALUE时,dwMaximumSizeHigh/Low决定总大小,与磁盘无关 - 传真实文件句柄时,
dwMaximumSizeHigh/Low不能小于文件实际大小,否则MapViewOfFile可能只映射前一部分 - 文件打开时若用了
FILE_ATTRIBUTE_TEMPORARY,系统可能跳过磁盘写缓存 → 对后续映射读性能有隐性提升
释放顺序错了会导致句柄泄漏还是崩溃?
不会崩溃,但会泄漏内核资源:UnmapViewOfFile必须在CloseHandle(hMap)之前调用,且每个MapViewOfFile配一个UnmapViewOfFile。Windows允许重复UnmapViewOfFile,但CloseHandle(hMap)后继续UnmapViewOfFile会失败(返回FALSE,GetLastError()为ERROR_INVALID_HANDLE)。
最容易被忽略的一点:映射指针本身不是句柄,不能用CloseHandle关;而hMap一旦关闭,所有基于它的映射视图自动失效,再访问就是访问非法内存(AV异常)。
- 典型安全模式:先
UnmapViewOfFile(pView),再CloseHandle(hMap),最后CloseHandle(hFile) - 多线程中若多个线程共用同一映射视图,确保所有线程停止访问后再
UnmapViewOfFile - RAII封装时,析构函数里按上述逆序释放,且对
pView和hMap加空指针检查
映射大文件时,页错误处理、NUMA节点亲和性、以及映射区域是否跨页边界对性能影响远大于API调用本身——这些不在CreateFileMapping接口层面暴露,但实测中常成为瓶颈。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










