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

Linux下TCC JIT编译C代码因内存访问与DS寄存器冲突致x86/x64 SIGSEGV

TCC JIT 常量地址写回导致SIGSEGV的解决方案

问题根因

出现SIGSEGV是因为TCC在64位模式下处理直接常量地址的写回操作时,错误地对64位地址做了32位符号扩展:原本的用户态地址0x7ffff5e1b020被截断为低32位0xf5e1b020,再符号扩展成64位的0xfffffffff5e1b020(属于内核空间地址),写操作自然触发段错误。这是TCC代码生成阶段的bug,和volatile关键字无关——volatile仅控制优化策略,无法修复地址处理逻辑。

解决办法

1. 显式传入64位地址常量

放弃使用%p格式符,改用0x%llx将地址转换为64位十六进制常量传入,让TCC直接识别为完整的64位地址:

// 修改ADD_CODE的格式串和参数
ADD_CODE("if ((*((volatile U64*)(0x%llx)) += %d) >= *((volatile U64*)(0x%llx))) {\n", 
         (unsigned long long)&a, 1, (unsigned long long)&b);

这样生成的汇编会用完整的64位立即数做地址访问,避免符号扩展问题。

2. 用指针变量中转地址

先将常量地址赋值给局部指针变量,再通过指针访问内存。这种方式会让TCC用寄存器保存指针,写回时采用寄存器间接寻址,绕开直接常量地址的bug:

ADD_CODE("volatile U64 *ptr_a = (volatile U64*)0x%llx;\n"
         "volatile U64 *ptr_b = (volatile U64*)0x%llx;\n"
         "if ((*ptr_a += %d) >= *ptr_b) {\n",
         (unsigned long long)&a, (unsigned long long)&b, 1);

3. 升级TCC到最新版本

这个地址截断问题大概率是旧版TCC的64位代码生成bug,升级到官方最新版(比如tcc-0.9.28或更高)可能已经修复该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:22:37