日期:2014-05-16 浏览次数:20713 次
一、案例
编译出一个动态库.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