C代码访问指定地址触发段错误但GDB中可正常访问问题咨询
异常现象成因
1. 段错误的核心原因
你当前的程序是开启了PIE(位置无关可执行)的动态链接程序(objdump 标记为DYNAMIC),同时你通过链接脚本将存储data变量的.ipl1_interface段的VMA(虚拟内存地址)强行指定为了0x12345678:
- 正常运行时,操作系统加载器只会映射符合常规地址布局的段,对于这种被手动指定了非规范VMA的自定义段,加载器默认不会将其映射到进程的虚拟地址空间中。你硬编码
dataPtr为0x12345678,访问该地址时对应的内存没有实际映射,因此触发段错误。
2. GDB 可正常访问的原因
GDB 作为调试工具做了特殊适配:
- GDB 会读取 ELF 文件的全量段信息和符号表,当你执行
p *(int *)dataPtr时,GDB 识别到0x12345678对应data符号,会直接从 ELF 文件的对应段中读取你初始化的数值5,而非强制访问进程的虚拟地址空间; - 部分版本的 GDB 启动调试进程时,会主动将所有标记为
ALLOC的段按其指定的VMA映射到进程地址空间,因此 GDB 环境下该地址是合法可访问的。
验证方法
你可以通过以下操作复现异常,验证上述结论:
- 正常运行程序前关闭系统 ASLR:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space - GDB 内开启 ASLR 后再运行程序:
set disable-randomization off
如果此时 GDB 内也触发段错误,即可确认是加载器的段映射逻辑导致的问题。
内容的提问来源于stack exchange,提问作者Umar
相关产品推荐
相关产品推荐

