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

NASM调用_malloc后内存越界写入未触发段错误的原因咨询

问题:macOS下NASM调用C库_malloc越界写入未触发段错误

我在macOS系统下使用NASM编写汇编代码,尝试调用C库的_malloc进行动态内存分配,目标是分配10字节内存,但发现向分配块外写入数据时,程序并未触发segfault(段错误)。

我最初尝试按Christopher Swenson的方式将大小压入栈中传参,之后参考较新资料将大小存入rdi寄存器,最终采用了后者的方式。以下是测试代码:

extern _malloc ;; malloc from the C library
section .text
    global _start

_start:
  xor rdi, rdi
  mov rdi, 10         ;; 尝试分配10字节
  call _malloc        ;; 返回的地址存在rax中
  mov qword [rax], 1  ;; 向合法区域写入数据
  add rax, 11         ;; 偏移到分配块外
  mov qword [rax], 1  ;; 向非法区域写入数据,但未触发错误

  mov rax, 0x2000001
  mov rdi, 0
  syscall

为简化操作,我未对返回值rax是否为NULL进行校验。编译命令如下:

$ nasm -f macho64 -o test.o test.asm
$ gcc -e _start test.o -lc -m64 -o a.out -Wl,-no_pie

恳请解释我是否正确使用了_malloc,或是为何越界写入未触发段错误?


回答

1. 你对_malloc的调用是正确的

macOS的64位环境采用System V AMD64调用约定,第一个参数通过rdi寄存器传递,所以你将分配大小10存入rdi后调用_malloc的写法完全符合规范。之前压栈传参的方式属于32位或者旧的调用约定,不适用于64位macOS,你改用寄存器传参的选择是对的。

2. 越界写入未触发段错误的原因

这是malloc内存分配机制的正常现象,核心原因有两点:

  • 内存块的额外分配与对齐:macOS的malloc实现(底层是libmalloc)不会严格只分配你请求的字节数。为了满足内存对齐要求(通常是16字节或更大粒度)、维护内存块的管理元数据(比如块大小、分配状态等头部信息),以及减少频繁分配的开销,它会分配比你请求更大的内存块。你这里偏移11字节后写入,大概率还在这些额外分配的、属于当前进程的内存空间内,没有触及虚拟内存的页边界。
  • 段错误的触发条件:段错误只有当进程访问了不属于自己的虚拟内存页时才会触发。malloc分配的内存块周围的额外空间仍然属于当前进程的地址空间,所以写入时不会立刻触发错误,但这种行为属于未定义行为——后续可能会破坏其他内存块的元数据或者覆盖其他变量,导致程序在后续操作中崩溃,只是没在你写入的瞬间显现。

如果想验证,可以尝试更大的偏移量,比如add rax, 1024后再写入,此时大概率会触发段错误,因为已经超出了malloc为该块额外分配的空间范围。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:15:05