动态库编译环境 CPLUS_INCLUDE_PATH 引发的bug追踪定位过程

动态库编译环境 CPLUS_INCLUDE_PATH 引发的bug追踪定位过程

问题背景:

最近做项目,同一份动态库代码,A同学编译出来可以正常加载运行; B同学编译也能成功,但加载的时候提示 动态库有未定义符号 XXXX。 A同学编译出来的so里面,没有这个符号。

 

问题定位过程:

1. 用nm 查看未定义符号XXXX : nm a.so | grep XXXX 查看该符号是不是 未定义的。

2. 查看这个未定义的符号来自哪里。   看看nm的参数有没有办法把源文件打印出来。

nm [option(s)] [file(s)]

有用的options:

  • -A 在每个符号信息的前面打印所在对象文件名称;
  • -C 输出demangle过了的符号名称;
  • -D 打印动态符号;
  • -l 使用对象文件中的调试信息打印出所在源文件及行号;
  • -n 按照地址/符号值来排序;
  • -u 打印出那些未定义的符号;

nm -l a.so | grep XXXX 查看到下面的信息

nm告诉我们为定义符号来源于 libcryto.so.xx库,但这个库却没有这个未定义符号。说明nm给出的信息有误。

3. 那如何找到这个未定义的符号来源哪里呢?    我们知道so是由一组 *.o 文件经过  -fPIC -shared 链接而来。我们可以去 *.o 文件中去找是哪里引入这个未定义符号。

cd 到编译目录,然后 nm *.o | grep XXXX 看到的信息如下:

4. 找到了引起这个未定义的cpp文件,这个时候就要问 为什么A同学编译的文件没问题, B同学编译的提示 未定义符号。    这时候我们就需要把源CPP的预编译文件打印出来后对比下了。

使用 g++ -E 命令生成预编译文件 output.i. 然后在这个文件中搜索未定义符号 XXXX. 发现它来自  /usr/local/include/openssl/evp.h 这个头文件。  这时候就想, 如果A同学编译也用到这个头文件,编译出来的so也应该包含 未定义符号。但A同学编译出来的so没有这个符号,很神奇。

5. 在A同学的环境中也生成预编译文件,然后在里面查找 enp.h 文件的路径。 发现A同学用的是  /usr/include/openssl/evp.h 目录下的头文件。 原来两个人用的头文件不是同一个。通过对比两个目录下的evp.h,发现他们是两个版本,里面的内容变动很大。 /usr/include/openssl/evp.h里面没有未定义的符号。 原因找到了。

6. 那A同学的环境里面多了什么,或者少了什么, 导致查找系统头文件目录的优先级发生了变动?   通过查询信息,发现:

gcc 在编译时如何去寻找所需要的头文件 :

※所以header file的搜寻会从-I开始

※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH。 C_INCLUDE_PATH仅对预处理C有效,CPLUS_INCLUDE_PATH仅对预处理C++有效,而CPATH对所有语言均有效。

※再找内定目录

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g -3

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

这里去A同学的环境变量中查找有没有设置 CPLUS_INCLUDE_PATH。  果然,A同学配置了这样的信息

,而B同学没有配置。 至此问题的根本原因发现了

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值