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

编译时使用.rodata与-fPIE选项出现重定位错误的问题求助

解决汇编与C混合编译中.rodata段的R_X86_64_32S重定位错误

问题根源

你的个人机器GCC默认启用PIE(位置无关可执行文件)编译模式,而学校服务器可能默认关闭该模式。汇编文件func_select.s中对.rodata段的引用使用了32位绝对地址重定位(R_X86_64_32S),这种方式与PIE模式不兼容,导致链接报错。

错误分析

  • 你之前把-fPIE/-no-pie放在-o和a.out之间,属于参数顺序错误:-o选项必须紧跟输出文件名,GCC会误将-fPIE当成输出文件,因此报错找不到a.out。
  • 仅在链接阶段加-fPIE无效,因为旧的func_select.o是用非PIE模式编译的,必须重新编译所有目标文件才能适配PIE规则。

解决方案

方案1:禁用PIE模式(最适配学校作业代码)

修改Makefile,给编译、链接全阶段添加-no-pie选项,确保所有目标文件都以非PIE模式生成:

# 编译选项:-g用于调试,-no-pie禁用PIE
CFLAGS = -g -no-pie
ASFLAGS = -g -no-pie
# 链接选项
LDFLAGS = -no-pie

# 最终可执行文件规则
a.out: main.o run_main.o func_select.o pstring.o
	gcc $(CFLAGS) $(LDFLAGS) -o $@ $^

# C文件编译规则
%.o: %.c
	gcc $(CFLAGS) -c $< -o $@

# 汇编文件编译规则(原Makefile未定义时需添加)
%.o: %.s
	gcc $(ASFLAGS) -c $< -o $@

执行以下命令重新编译:

make clean  # 清除旧目标文件和可执行文件
make

方案2:修改汇编代码适配PIE模式(适合理解PIE原理)

如果想保留PIE模式,需修改汇编文件中对.rodata的引用方式,改用RIP相对寻址。例如:
原绝对地址引用:

movl $.rodata_str, %eax

改为RIP相对寻址:

leaq .rodata_str(%rip), %rax

这种方式使用R_X86_64_PC32重定位,兼容PIE模式。修改后用-fPIE重新编译:

CFLAGS = -g -fPIE
ASFLAGS = -g -fPIE
LDFLAGS = -fPIE

a.out: main.o run_main.o func_select.o pstring.o
	gcc $(CFLAGS) $(LDFLAGS) -o $@ $^

%.o: %.c
	gcc $(CFLAGS) -c $< -o $@

%.o: %.s
	gcc $(ASFLAGS) -c $< -o $@

关键注意点

  • 编译选项顺序不可乱:-o后面必须直接跟输出文件名,不能插入其他选项。
  • 修改Makefile后务必先清除旧目标文件,否则旧.o文件会继续引发冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:55:16