x86_64汇编调用brk分配堆内存写入0x999以上地址触发段错误如何解决
问题原因
- 核心错误是堆地址取值逻辑错误:
heapStart是你在.data段定义的8字节变量,作用是存储brk返回的堆内存起始地址。但你代码中执行mov rdi, heapStart时,是把heapStart变量自身的虚拟地址(属于数据段地址范围)赋值给了rdi,而非取出该变量中存储的堆内存起始地址。你后续基于数据段地址做0x1000偏移写入,已经超出了数据段的合法映射范围,因此触发SIGSEGV段错误。 - 你调用brk申请0x4000字节堆内存的逻辑本身没有问题,错误完全来自地址取值环节。
修复方案
将代码中mov rdi, heapStart修改为mov rdi, [heapStart]即可:方括号在NASM语法中表示取地址对应存储的内容,这行修改后你拿到的就是真正的堆内存起始地址,后续基于该地址的偏移写入都会落在你申请的合法堆内存区间内。
修复后的完整可运行代码如下:
global _start section .data heapStart: dq 0 ; 存储堆起始地址 section .text _start: mov rax, 12 ; brk系统调用号 mov rdi, 0 syscall ; 获取当前堆顶作为堆起始地址 mov QWORD [heapStart], rax ; 保存堆起始地址 lea rdi, [rax + 0x4000] mov rax, 12 syscall ; 抬高堆顶0x4000字节,完成内存申请 mov rdi, [heapStart] ; 取出堆起始地址,修复点 mov BYTE [rdi + 0x1000], 'b' ; 写入合法堆地址,无段错误 mov rax, 60 ; exit系统调用 mov rdi, 0 ; 退出码 syscall
内容的提问来源于stack exchange,提问作者Ari
相关产品推荐
相关产品推荐

