一、案例

     编译出一个动态库.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

 

              U _ZN11CHttpParser20GetCurrentHttpMethodER13http_method_t
                 U _ZN11CHttpParser26ExactResultFromHttpMsgBodyESsRSs
                 U _ZN11CHttpParser5parseESs
                 U _ZN11CHttpParserC1ESs

00000000000134e6 W _ZN5boost10shared_ptrI11CHttpParserE4swapERS2_
0000000000012e56 W _ZN5boost10shared_ptrI11CHttpParserEC1ERKS2_
0000000000012e30 W _ZN5boost10shared_ptrI11CHttpParserEC1Ev
0000000000014cda W _ZN5boost10shared_ptrI11CHttpParserEC1IS1_EEPT_
0000000000012cda W _ZN5boost10shared_ptrI11CHttpParserED1Ev
0000000000013df4 W _ZN5boost10shared_ptrI11CHttpParserEaSERKS2_
000000000001348b W _ZN5boost14checked_deleteI11CHttpParserEEvPT_
0000000000014c4c W _ZN5boost6detail12shared_countC1I11CHttpParserEEPT_
0000000000013bae W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserE11get_deleterERKSt9type_info
0000000000013b92 W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserE7disposeEv
0000000000013452 W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserEC1EPS2_
0000000000014d1e W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserED0Ev
0000000000014d5a W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserED1Ev
000000000001591c W _ZNK5boost10shared_ptrI11CHttpParserEptEv
00000000000134b4 W _ZSt4swapIP11CHttpParserEvRT_S3_
000000000021ba40 V _ZTIN5boost6detail17sp_counted_impl_pI11CHttpParserEE
0000000000017420 V _ZTSN5boost6detail17sp_counted_impl_pI11CHttpParserEE
000000000021ba00 V _ZTVN5boost6detail17sp_counted_impl_pI11CHttpParserEE
0000000000017100 r _ZZNK5boost10shared_ptrI11CHttpParserEptEvE19__PRETTY_FUNCTION__

 

 

命令输出结果显示,那些报错的函数的符号 同样可以在nm里找到。

不同的是,这四个出错的函数,输出的前半部分为空。

这就是异常和问题所在!

 

下面我们只要对nm命令稍作了解:

nm命令还是比较简单而且强大的。它用来列出一个目标文件中的各种符号。符号的种类很多,以下是一些常见的符号类型

nm输出字符 含义
R Read only symbol. 比如在代码中有一个const MAXDATA = 3095; 则MAXDATA就是一个Read only symbol
N 这是一个调试符号
D 这是一个已经初始化的变量的符号。比如代码中int i = 1和char *str = “Hello”则i和str都是这种类型的符号
T Text段的符号。子程序都是这种符号,比如文件中实现了一个函数function,则function就是这种符号
U 未定义的符号。如果文件中引用了不存在的函数,则这些未定义的函数符号就是这种类型
S 未初始化的符号,比如全局变量int s;则s的符号就是此类型

nm命令的详细用法以及例子见正文。

 

至此,我们可以推断:动态库中有未定义的符号,说明该动态库的编译有问题,即是如下原因之一:

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

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

这种问题的解决,首先就要检查动态库的makefile写的是否有问题。

果然,发现makefile里没有把该出错函数所在的定义的源文件没有编译进去。

 

 

三 问题解决

     找到了原因,问题解决就方便了。修改.so的makefile即可。

svn diff

-COM_SRCS := $(GENASRCDIR)/CGenaEngine.cpp
+COM_SRCS := $(GENASRCDIR)/CGenaEngine.cpp   $(HTTPSRCDIR)/CHttpMiniParser.cpp   —–》把CHttpMiniParser.cpp  编译进去。

 

原文地址:http://www.cnblogs.com/lidabo/p/16845989.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性