Linux编译程序报错 undefined reference to error 的解决方法

对于我这个刚入IT行业不就得新手来说,在linux下链接库的时候总是会遇到各种各样奇葩的问题,最多的就是“undefined reference to”和“cannot find”这两类,层出不穷,总是在我即将完成工作的时候给我当头一棒,让我欲罢不能。这不,这几天编译linux下一个项目时又遇到难题了。

        在我编译的项目中,其中需要编译一个静态库(下面命名为libA.a),而libA.a需要依赖另外两个动态库(下面命名为libB.so和libC.so),刚开始在编译libA.a时,提示找不到libB.so和libC.so里面的函数接口。然后看了一下Makefile,便发现了原因。这个不难。原来是我只在由.o文件连接成.a文件时有链接了libB.so和libC.so动态库,但是在由.c编译成.o时并没有链接libB.so和libC.so。所以这一步直接提示找不到动态库里面的函数接口。按照上面的错误原因修改Makefile之后,便轻易地编译成功了。

        就在我以为一切都大功告成的时候,我才发现我又高兴的太早了。当我将编译好的libA.a以及它所依赖的libB.so和libC.so都连接在项目中时(像我一样的新手千万别忘了,这个依赖的是动态库,要连同一起连接在项目中,我就吃过亏),编译出现的错误,错误内容还是“undefined reference to”libB.so和libC.so里面的函数接口。我当时就蒙了,这是什么情况,我明明都链接进去了啊,为什么还是这样。从错误的提示内容可以看出libA.a里面的函数接口都正常,唯独libB.so和libC.so他们两个里面的函数接口找不到。我就怀疑是不是没有找到这两个动态库或者链接出错之类的,折腾了一会我发现我又错了,如果没链接成功会有类似“cannot find”之类的提示。所以说链是链接上了,可为什么还是找不到呢。就在我百思不得其解时,突然一个念头从脑海中闪过“顺序”,难道问题是出在我连接库的顺序上?当前的顺序是先连接的libB.so和libC.so,然后再链接libA.a。于是我抱着一丝希望将libA.a调到了libB.so和libC.so两个前面,先连接libA.a,运行make。。。真TM编过了。哎,看来真的是年轻啊。

        至于为什么会这样,在这就不多废话了,有兴趣的码友可以专门去了解一下

=====================================================================================

Linux下编译程序时,经常会遇到“undefined reference error” 报错,这里总结一些可能的原因和解决方案,给需要的朋友。

说到undefined reference error,先提一下Linux gcc链接规则。

链接的时候查找顺序是:

-L 指定的路径, 从左到右依次查找

由环境变量LIBRARY_PATH 指定的路径,使用":"分割从左到右依次查找

/etc/ld.so.conf 指定的路径顺序

/lib 和/usr/lib (64位下是/lib64和/usr/lib64)

动态库调用的查找顺序:

ld的-rpath参数指定的路径, 这是写死在代码中的

ld脚本指定的路径

LD_LIBRARY_PATH 指定的路径

/etc/ld.so.conf 指定的路径

/lib和/usr/lib(64位下是/lib64和/usr/lib64)

一般情况链接的时候我们采用-L的方式指定查找路径,调用动态链接库的时候采用LD_LIBRARY_PATH的方式指定链接路径。

另外注意一个问题,就是只要查找到第一个就会返回,后面的不会再查找。比如-L./A -L./B -lx 在A中有libx.a B中有libx.a和libx.so, 这个时候会使用在./A的libx.a 而不会遵循动态库优先的原则,因为./A是先找到的,并且没有同名动态库存在。

对于动态链接库,实际的符号定位是在运行期进行的。在编译.so的时候,如果没有把它需要的库和他一起进行联编,比如libx.so 需要使用uldict, 但是忘记在编译libx.so的时候加上-luldict的话,在编译libx.so的时候不会报错,因为这个时候libx.so被认为是一个库,它里面存在一些不知道具体实现的符号是合法的,是可以在运行期指定或者编译另外的二进制程序的时候指定。

如果是采用 g++ -Lpath -lx 的方式进行编译,链接器会发现所需要的uldict的符号表找不到从而报错,但是如果是程序采用dlopen的方式载入,由于是运行期,这个程序在这个地方就直接运行报错了。另外还有一种情况就是一个对外的接口在动态库中已经声明定义了,但是忘记实现了,这个时候也会产生类似的错误。

如果在运行期报出这样的错误,就要注意是否是由于某些库没有链接进来或者某些接口没有实现的原因产生。

有了上述基础,不难总结出,undefined reference error错误的原因可能来自以下几方面:

1 没有指定对应的库(.o/.a/.so)

使用了库中定义的实体,但没有指定库(-lXXX)或者没有指定库路径(-LYYY),会导致该错误。

2 连接库参数的顺序不对

在默认情况下,对于-l 使用库的要求是越是基础的库越要写在后面,无论是静态还动态。

3 gcc/ld 版本不匹配

gcc/ld的版本的兼容性问题,由于gcc2 到gcc3大版本的兼容性存在问题(其实gcc3.2到3.4也一定程度上存在这样的问题) 当在高版本机器上使用低版本的机器就会导致这样的错误, 这个问题比较常见在32位的环境上, 另外就在32位环境不小心使用了64位的库或者反过来64位环境使用了32位的库。

4 C/C++相互依赖和链接

gcc和g++编译结果的混用需要保证能够extern "C" 两边都可以使用的接口,在64位环境中gcc链接g++的库还需要加上-lstdc++,具体见前文对于混合编译的说明。

5 运行期报错

这个问题基本上是由于程序使用了dlopen方式载入.so, 但.so没有把所有需要的库都链接上,具体参加上文中对于静态库和动态库混合使用的说明。

原链接:http://www.2cto.com/os/201112/113315.html

===========================================================

lib/libQtGui.so: undefined reference to `ts_read_raw’

/lib/libQtGui.so: undefined reference to `ts_open’

/lib/libQtGui.so: undefined reference to `ts_fd’

/lib/libQtGui.so: undefined reference to `ts_config’

/lib/libQtGui.so: undefined reference to `ts_close’

/lib/libQtGui.so: undefined reference to `ts_read

解决办法:

‘修改qt-everywhere-opensource-src-4.7.2/mkspecs/qws/linux-arm-g++/qmake.conf 文件(添加lts参数):

QMAKE_CC = arm-linux-gcc -lts

QMAKE_CXX = arm-linux-g++ -lts

QMAKE_LINK = arm-linux-g++ -lts

QMAKE_LINK_SHLIB = arm-linux-g++ -lts

猜你喜欢

转载自blog.csdn.net/mw_nice/article/details/84847697