美团二面:为什么mmap共享内存比malloc危险?
大家好,我是小风哥,畅销书《计算机底层的秘密》作者。
今天来聊个面试题,为什么mmap共享内存比malloc更危险,这是一个比较有区分度的题目。
在系统编程中,内存管理是程序员必须面对的核心问题之一。
C/C++开发者常用的内存分配方式包括malloc(堆内存)和mmap(共享内存/文件映射)。

虽然两者都能提供内存分配的能力,但从系统风险的角度来看,mmap共享内存比malloc更加危险,稍有不慎就可能引发严重的安全漏洞或稳定性问题。
mmap共享内存可能导致其它进程崩溃
mmap可以让多个进程直接读写同一块物理内存,这意味着一个进程的错误操作可能直接影响其他进程的数据,甚至导致崩溃。比如进程A的越界写入可能导致进程B崩溃或读取到损坏的数据。
一句话,共享内存破坏了进程间的内存隔离。

而如果使用malloc,这种越界写入最多只会影响当前进程,不会跨进程传播错误。因为malloc分配的内存仅在当前进程内有效,天然具备隔离性,其他进程无法直接访问。
mmap的权限风险
mmap可以设置内存的读写/执行权限(如PROT_EXEC),如果错误配置可能被黑客利用进行代码注入攻击(如缓冲区溢出后执行恶意代码)。

假设有一个网络服务程序,使用 mmap 分配了一块内存用于处理客户端请求,并错误地赋予了可执行权限(PROT_EXEC):
void *mem_start = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
同时,程序将用户输入数据(如网络数据包)复制到该内存区域,但未检查输入长度。
这样攻击者就可以构造一个超长数据包,其中包含恶意机器码(如 shellcode)和精心设计的溢出数据,溢出数据覆盖了程序的返回地址或函数指针,使其指向 mem_start 的起始地址。
当程序执行到该返回地址时,会跳转到 mem_start 区域。

由于 mem_start 被错误配置为可执行(PROT_EXEC),因此操作系统不会阻止该区域的代码执行。
攻击者的 shellcode 被成功执行,可能实现提权、反弹 Shell 等恶意操作。
而使用malloc分配的堆内存则无此问题。
多线程与同步风险
使用mmap共享内存时,多进程或线程需通过信号量、锁等机制同步访问,否则导致数据竞争(Data Race)或脏读,这显然会影响所有共享这块内存的进程。

malloc本身是线程安全的(通过全局锁或线程本地缓存),但程序员需自行管理分配的内存区域的并发访问。若未加锁,仍可能导致竞争条件,但与mmap的共享内存相比,影响范围限于当前进程内。





