在RHEL编译C++类库时遇链接错误及异常运行行为求助
问题分析:RHEL环境下C++共享库链接错误及运行异常问题
一、链接错误的成因
你遇到的R_X86_64_32重定位错误,核心原因是构建共享库时未生成位置无关代码(PIC):
- x86_64架构下,共享库需要以位置无关的方式编译,这样加载时可以被映射到进程的任意内存地址。编译时必须添加
-fPIC参数,否则编译器会生成依赖固定内存地址的32位重定位指令,而共享库不支持这种重定位类型。 - 为什么不同
printf用法会触发不同结果?这是GCC对printf的特殊优化导致的:- 当格式串是极简的
"%c"时,编译器会将其直接优化为putchar()调用,不需要在.rodata段存储格式字符串,也就不会触发涉及.rodata的32位重定位,因此能侥幸完成链接。 - 当格式串包含更多内容或其他转换说明符时,编译器会将格式字符串存入
.rodata段,此时未加-fPIC编译的目标文件会生成针对该段的32位重定位,链接共享库时就会触发明确错误:/usr/bin/ld: xor.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Nonrepresentable section on output
- 当格式串是极简的
你的Makefile编译共享库的命令缺少-fPIC,同时建议用g++链接C共享库(避免gcc链接时遗漏C标准库依赖),正确的构建命令应为:
libxor.so: xor.cpp g++ -c -fPIC -o xor.o xor.cpp g++ -shared -o libxor.so xor.o drv: drv.cpp libxor.so g++ -o drv drv.cpp -L/home/xxx/source -lxor
二、运行输出异常的原因
能构建的版本(仅用printf("%c", plainText[curSubscript]))输出不符合预期,本质是未加-fPIC编译的目标文件,即使侥幸链接成功,代码存在地址访问错误:
- 虽然优化后的
putchar()调用没触发链接错误,但整个目标文件并非合法的位置无关代码。当共享库被加载到进程内存时,全局变量、数组(比如你的plainText)的地址计算会出现偏差,导致访问到错误的内存位置,输出自然不是预期的字符。 - 这种“侥幸构建”是编译器优化带来的特例,并非合法的共享库构建方式,运行时的行为完全不可靠。
内容的提问来源于stack exchange,提问作者Paul CyberCitizen
相关产品推荐
相关产品推荐

