munmap只是解除虚拟地址映射,不立即释放物理页;内核延迟回收,直至复用或内存压力上升,rss不降不表示失败,只要返回0即成功。

munmap 为什么调用后内存没立刻释放?
munmap 只是解除虚拟地址映射,并不保证物理页立即回收。内核会延迟释放,直到该内存区域被其他 mmap 复用或系统内存压力上升时才真正归还物理页。常见误解是看到 top 或 ps 的 RSS 没降,就以为 munmap 失败了——其实只要返回 0 就成功解除了映射。
- 必须传入与
mmap返回值完全一致的地址(对齐到页面边界) - 长度参数必须是页面大小的整数倍(
getpagesize()),否则行为未定义 - 解除映射后访问该地址会触发
SEGV_MAPERR(段错误),不是“还能读到旧数据”
munmap 参数不对齐导致 EINVAL 错误
munmap 要求地址是页面对齐的,且长度非零。如果用 mmap 返回的指针直接传入但没校验对齐,或长度算错(比如用了对象大小而非页对齐后的大小),就会返回 -1 并设 errno = EINVAL。
- 用
reinterpret_cast<uintptr_t>(addr) % getpagesize() == 0</uintptr_t>检查地址对齐 - 长度应为
((size + getpagesize() - 1) / getpagesize()) * getpagesize() - 若原始
mmap是用MAP_ANONYMOUS分配的,也必须用同样对齐后的长度调用munmap
void* ptr = mmap(nullptr, 1000, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (ptr == MAP_FAILED) { /* handle */ }
size_t page_size = getpagesize();
size_t aligned_len = ((1000 + page_size - 1) / page_size) * page_size;
// ✅ 正确:用对齐后的长度
munmap(ptr, aligned_len);
// ❌ 错误:用 1000 会导致 EINVAL(除非 page_size == 1)
// munmap(ptr, 1000);
munmap 后继续使用指针的典型崩溃场景
解除映射后指针变成悬空指针,但不会自动置为 nullptr。后续解引用、传给 free、或再次 munmap 都是未定义行为——可能当场段错误,也可能静默破坏其他内存。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 不要对已
munmap的地址调用free(它不属于堆) - 不要重复调用
munmap(第二次会返回 -1,errno = EINVAL) - 如果封装成 RAII 类,务必在析构中
munmap,且把指针设为nullptr(仅作防御,不改变未定义行为本质)
和 malloc/free 混用会出什么问题?
munmap 和 malloc/free 管理的是不同内存区域:malloc 通常基于 sbrk 或 mmap(大块时),但用户不可见;直接对 malloc 返回的指针调用 munmap 是危险的。
-
munmap(ptr, len)中的ptr必须是之前mmap成功返回的地址 - 对
malloc返回值调用munmap极大概率触发段错误,因为地址不在内核维护的 VMA 区间内 - 想释放堆内存,请始终用
free;想用munmap,就得自己用mmap分配
关键点容易被忽略:即使 mmap 成功,也要检查返回值是否为 MAP_FAILED;即使 munmap 成功,也不能假设物理内存立刻归还;地址和长度的页面对齐不是可选项,是硬性要求。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










