GCC链接时动态库搜索方式以及“undefined reference to '_Unwind_GetIPInfo@GCC_4.2.0'”解决

当项目依赖的库与系统默认库版本冲突时,会导致编译错误。本文介绍了如何通过设置`LD_LIBRARY_PATH`环境变量或修改Makefile来解决这种`undefined reference`问题,确保链接时使用正确的库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境介绍 :

目标机上安装了两个版本gcc:gcc 3.36,gcc 4.41。makefile 使用gcc 3.36编译的。

Makefile链接部分:

FLAGS_LIB_PATH=-L../lib
FLAGS_LIB=-ldl -lxml++-2.6 -lcurl -lstdc++ ../lib/libstdc++.so.6

...

$(DIR_OUT)/$(FILE_OUT):$(OBJS_CPP) $(OBJS_CC)
$(LINK.cc) $(FLAGS_LINK) -o $@ $(addprefix $(DIR_OBJ)/,$(notdir $^)) $(FLAGS_LIB_PATH) $(FLAGS_LIB)
$(INSTALL_COMMAND)

问题:

项目依赖的libxml++2.6.so 依赖的GCC4.2.0 libstdc++.so.6, 这个库事先已经放在../lib 目录下了,但是/usr/lib目录下也有一个libstdc++.so.6库,这个是gcc 4.41安装的。

编译时出现:

linux-83nz:/home/projects/study/TestCURL # make
/opt/gcc-3.3.6/bin/g++ -o /home/projects/study/TestCURL/bin/testcurl /home/projects/study/TestCURL/bin/main.o /home/projects/study/TestCURL/bin/mycurl.o /home/projects/study/TestCURL/bin/myparser.o -L../lib -ldl -lxml++-2.6 -lcurl -lstdc++
/usr/bin/ld: warning: libstdc++.so.6, needed by ../lib/libxml++-2.6.so, may conflict with libstdc++.so.5
/usr/bin/ld: warning: libstdc++.so.6, needed by ../lib/libxml++-2.6.so, may conflict with libstdc++.so.5
/usr/lib/libstdc++.so.6: undefined reference to `_Unwind_GetIPInfo@GCC_4.2.0'
collect2: ld returned 1 exit status
make: *** [/home/projects/study/TestCURL/bin/testcurl] 错误 1

原因分析:

libxml++2.6.so依赖的库libstdc++.so.6会自动按照共享库搜索方式,搜索到该gcc 4.41下的,因此会提示链接错误。


解决方案:
1.使用LD_LIBRARY_PATH解决:

将搜索路径明确指定到../lib下,编译通过,如下:
linux-83nz:/home/projects/study/TestCURL # export LD_LIBRARY_PATH=../lib
linux-83nz:/home/projects/study/TestCURL # make
/opt/gcc-3.3.6/bin/g++ -o /home/projects/study/TestCURL/bin/testcurl /home/projects/study/TestCURL/bin/main.o /home/projects/study/TestCURL/bin/mycurl.o /home/projects/study/TestCURL/bin/myparser.o -L../lib -ldl -lxml++-2.6 -lcurl -lstdc++
/usr/bin/ld: warning: libstdc++.so.6, needed by ../lib/libxml++-2.6.so, may conflict with libstdc++.so.5
/usr/bin/ld: warning: libstdc++.so.6, needed by ../lib/libxml++-2.6.so, may conflict with libstdc++.so.5

2.修改Makefile解决:

修改Makefile链接选项FLAGS_LIB ,明确加上../lib/libstdc++.so.6,使之在指定目录下查找,编译通过。

FLAGS_LIB=-ldl -lxml++-2.6 -lcurl -lstdc++ ../lib/libstdc++.so.6

结论:

GCC -l 没有指定的库是通过执行时搜索路径来找的

附录:

1. 查询当前共享库版本:

objdump -p /usr/lib/libstdc++.so.6 | grep SONAME

2. Shared libraries

Shared library 会在程序执行起始时才被自动加载。因为链接库与执行档是分离的,所以维护弹性较好。有两点要注意, shared library 是在程序起始时就要被加载,而不是执行中用到才加载,而且在连结阶段需要有该链接库才能进行连结。

首先有一些名词要弄懂, soname 、 real name 与 linker name 。

soname 用来表示是一个特定 library 的名称,像是 libmylib.so.1 。前面以 `lib' 开头,接着是该 library 的名称,然后是 `.so' ,接着
是版号,用来表名他的界面;如果接口改变时,就会增加版号来维护兼容度。

real name 是实际放有 library 程序的文件名,后面会再加上 minor 版号与
release 版号,像是 libmylib.so.1.0.0 。

一般来说,版号的改变规则是 ( 印象中在 APress-Difinitive Guide to GCC 中有提到,但目前手边没这本书 ) ,最后缀的 release 版号用于程序内容的修正,接口完全没有改变。中间的 minor 用于有新增加接口,但相旧接口没改变,所以与旧版本兼容。最前面的 version 版号用于原接口有移除或改变,与旧版不兼容时。

linker name 是用于连结时的名称,是不含版号的 soname ,如 : libmylib.so 。
通常 linker name 与 real name 是用 ln 指到对应的 real name ,用来提供弹性与维护性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值