mmap不能直接映射已存在的栈/堆数组,只能分配新虚拟内存区域并作为数组使用;需正确设置prot和flags,用munmap释放,Windows需用VirtualAlloc替代。

用 mmap 映射数组到虚拟内存需要绕过栈/堆分配
直接对普通数组(比如 int arr[1024])调用 mmap 是无效的——mmap 只能映射文件或匿名内存页,不能“重映射”已存在的栈/堆地址。真正可行的是:先用 mmap 分配一块可读写、可共享的虚拟内存区域,再把它当作数组来用。
常见错误现象:mmap 返回 MAP_FAILED,或者后续 memcpy 写入时触发 Segmentation fault,往往是因为没设对 prot(如漏掉 PROT_WRITE)或 flags(如该用 MAP_ANONYMOUS 却没加)。
- 若需进程内使用:用
MAP_ANONYMOUS | MAP_PRIVATE,不关联文件,类似malloc但可控权限和对齐 - 若需进程间共享:用
MAP_SHARED+ 文件描述符(如打开/dev/zero)或memfd_create(Linux 3.17+) - 注意页对齐:
length会自动向上对齐到系统页大小(getpagesize()),但起始地址由内核决定(除非用MAP_FIXED,慎用)
mmap 分配后怎么当数组访问?指针就是数组首地址
返回值是 void*,强制转成目标类型指针即可,下标访问完全合法。编译器不关心它来自 malloc 还是 mmap,只要地址有效、权限匹配。
#include <sys/mman.h>
#include <unistd.h><p>const size_t N = 1024;
int<em> arr = static_cast<int</em>>(mmap(nullptr, N <em> sizeof(int),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0));
if (arr == MAP_FAILED) { /</em> handle error */ }</p><p>arr[0] = 42; // ✅ 正常写入
arr[N-1] = 100; // ✅ 越界?不会立即报错,但可能踩到相邻页(未分配)导致 segfault</p>关键点:越界访问是否崩溃,取决于你踩到的是未映射页(立刻 SIGSEGV),还是已映射但无权限的页(SIGBUS),或恰好是另一块合法映射(静默出错)。别依赖“没崩=安全”。
立即学习“C++免费学习笔记(深入)”;
释放必须用 munmap,不能用 free
用 mmap 得来的内存块,其生命周期由内核管理,free 完全不认识它。混用会导致未定义行为——最轻是内存泄漏,严重时破坏 malloc 元数据,后续 malloc 崩溃。
- 释放方式唯一:
munmap(arr, N * sizeof(int)),且length必须和mmap时一致(或更大,但不能更小) - 如果只映射了部分区域(比如
mmap了 2MB,只用了前 1KB),仍要传入原始length,否则内核无法正确解映射 -
mmap返回的地址可能不是页首地址,但munmap会自动向下取整到页边界,所以传入原指针即可
Windows 上没有 mmap,得用 VirtualAlloc + VirtualFree
跨平台代码里硬写 mmap 会编译失败。Windows 对应机制是 VirtualAlloc,语义接近但参数不同:
// Windows 等效写法(需 #include <windows.h>)
LPVOID ptr = VirtualAlloc(nullptr, N * sizeof(int),
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (ptr == nullptr) { /* handle error */ }
int* arr = static_cast<int*>(ptr);
<p>// 释放
VirtualFree(ptr, 0, MEM_RELEASE);</p>注意:VirtualAlloc 的 MEM_COMMIT | MEM_RESERVE 一步到位,而 mmap 的 MAP_ANONYMOUS 默认就提交;PAGE_READWRITE 对应 PROT_READ | PROT_WRITE;但 Windows 没有直接等价于 MAP_SHARED 的匿名共享内存,需配合 CreateFileMapping 和 MapViewOfFile。
页大小在 Windows 通常是 4KB(GetSystemInfo 可查),和 Linux 一致,但对齐要求更严格:分配地址和长度都必须是页大小的整数倍。


















