You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS下mmap无法分配可执行页面的原因及修复方法

问题原因

macOS 13启用了严格的W^X(写异或执行)安全防护机制,核心规则就是同一块内存不能同时拥有写权限(PROT_WRITE)和执行权限(PROT_EXEC)。你当前的mmap调用同时指定了这两个权限,直接违反了系统的安全策略,所以哪怕mmap返回了有效指针,实际访问时也会触发段错误。

修复方法

得按W^X的规则来,分两步操作内存:

  • 先申请只有读写权限的匿名内存,把要执行的内容写进去;
  • 用mprotect把这块内存的权限改成执行+读权限,之后再执行里面的代码。

修改后的示例代码:

#include <sys/mman.h>
#include <stddef.h>
#include <stdio.h>
#include <errno.h>

int main() {
    size_t size = 100;
    // 第一步:申请仅读写权限的匿名内存
    char* buf = (char*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (buf == MAP_FAILED) {
        perror("mmap 失败");
        return 1;
    }

    // 往内存里写数据(如果是可执行代码,这里填对应的机器指令)
    *buf = 'a';

    // 第二步:修改权限为执行+读
    if (mprotect(buf, size, PROT_READ | PROT_EXEC) == -1) {
        perror("mprotect 失败");
        munmap(buf, size);
        return 1;
    }

    // 现在可以执行这块内存里的代码了(示例只是存了字符,实际替换成指令即可)
    // 比如调用函数:((void(*)())buf)();

    // 用完记得释放内存
    munmap(buf, size);
    return 0;
}
额外说明

如果是JIT这类需要动态修改代码的场景,可以先把权限改回读写,修改内容后再改回执行权限——但每次切换都得用mprotect,而且绝对不能同时开写和执行权限。macOS的这个W^X是系统强制规则,没法绕过,必须按这个流程来。

内容的提问来源于stack exchange,提问作者Mr User

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:47:27