日期:2014-05-16  浏览次数:20713 次

Linux下使用nm命令排查和解决“undefined reference to ”

一、案例

     编译出一个动态库.libXXXEngine.so。然后直接在另一个工程中,把头文件include进来,并link到该库:-lXXXEngine.

尝试编译,出错:

.//libXXXEngine.so:undefined reference to`CHttpParser::GetCurrentHttpMethod(http_method_t&)'

 

.//libGenaEngine.so: undefined reference to `CHttpParser::CHttpParser(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
.//libGenaEngine.so: undefined reference to `CHttpParser::ExactResultFromHttpMsgBody(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
.//libGenaEngine.so: undefined reference to `CHttpParser::parse(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status


从描述上看,以下四个函数没有定义:

 

(1) CHttpParser::GetCurrentHttpMethod(http_method_t&)

(2)CHttpParser::CHttpParser(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)

(3)CHttpParser::ExactResultFromHttpMsgBody(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'

(4)CHttpParser::parse(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)

 

然而奇怪的是,当我跟进libXXXengine.so的具体代码时,却发现头文件和源文件的定义和声明都可以找到。那么究竟什么原因呢?


二 问题分析

    出现这种错误,有几个原因:

(1)一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接。

(2)一是使用者自己定义的函数或者全局变量没有定义。

(3) 未定义的符号是一个动态库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题.

即:.so文件没有把所有需要的库都链接上。使用了库中定义的实体,但没有指定库(-lXXX)或者没有指定库路径(-LYYY),会导致该错误,

(4)C/C++相互依赖和链接
gcc和g++编译结果的混用需要保证能够extern "C" 两边都可以使用的接口,在我们的64位环境中gcc链接g++的库还需要加上 -lstdc++。

     经排查,我们在makefile中通过-lXXEngine正确链接了libXXXEngine.so,同时,我们也把相应的头文件放到我当前工程目录下了。然而,被告知且出错的函数都是在动态库中的。好奇怪!

    为了进一步找到问题的root cause,我们使用了nm命令来进一步排查:

nm libXXXEngine.so |grep CHttpParser