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

执行JIT生成的机器码后调用fprintf出现段错误问题求助

排查方向

1. 优先检查x86_64调用约定的寄存器保存规则

System V AMD64 ABI规定了被调用者保存寄存器列表:rbx、rbp、r12、r13、r14、r15。如果你的JIT代码修改了这些寄存器的值,必须在代码开头先压栈保存,执行结束后弹出恢复,否则返回C代码后,C程序依赖的寄存器上下文会被完全破坏。
你遇到的「循环变量n初始值错误为0x6C」「访问ic数组段错误」正好匹配这个问题:C代码中循环变量n可能被编译器分配到r12寄存器存储,而你的JIT代码直接修改了r12的值,导致回到C代码后n的初始值变成了0x6C,访问ic[0x6C]直接越界触发段错误。
修复方案:在JIT代码开头加上所有用到的被调用者保存寄存器的压栈操作,结尾按倒序弹出恢复,示例如下:

push rbx
push rbp
push r12
push r13
push r14
push r15
; 你的JIT业务代码
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
ret

2. 修正sysconf的传参错误

sysconf获取页大小的合法参数是_SC_PAGESIZE,不是直接传4096。传非法参数会导致sysconf返回-1,后续mmap、mprotect、munmap的长度参数全部异常,极易触发内存访问错误。同时你的代码重复定义了两次length变量,属于语法隐患建议删除重复定义。
修复后代码示例:

long page_size = sysconf(_SC_PAGESIZE);
if (page_size < 0) {
    // 错误处理
}
void * memory = mmap(0 , page_size , PROT_NONE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0);
if (memory == MAP_FAILED) {
    // 错误处理
}

3. 校验机器码拷贝长度和跳转地址合法性

  • 如果machine是指针类型,sizeof(machine)在64位系统下仅为8字节,不会返回机器码的实际长度,你需要传入实际生成的机器码长度作为memcpy的第三个参数,避免代码拷贝不完整执行非法指令。
  • 检查伪汇编中跳转偏移的计算逻辑,比如jmp 0xFFC8这类大偏移是否会跳出你分配的JIT内存范围,跳转到非法地址执行会直接触发段错误。

4. 检查内存访问越界问题

校验[Rn]访问mem数组时的偏移是否超出mem的实际长度,避免JIT代码执行时越界修改了栈上的ic数组、循环变量等C侧变量的值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 15:06:04