八字不合真的不能在一起吗?
先说答案,能的,只要不迷信。
当然,我说的是Linux下C++程序同时链接两个动态链接库后的调用时崩溃。
我学艺不精,浪费了一整天才定位到问题并找到解决方案,期间咨询了技术支持客服,百度,和其他老程序员。
剧情是这样的,我用金仕达提供的动态链接库libkcc.so采集加密的机器信息,用作期货的登陆委托,(去年期货新增穿透式监管,这是一个在量化交易开发中的普通需求)。这个库只需要用户调用金仕达头文件里唯一的一个函数KingStar_GetSystemInfo即可。

然后在Makefile里链接时加上libkcc.so。
so far so good
但是可能有些账户走的期货公司用的是CTP,那我还需要用CTP的动态链接库LinuxDataCollect.so给的函数获取机器信息,用法跟金仕达几乎一样,只是函数名不一样,叫CTP_GetSystemInfo。所以我的程序里就先后分别调用这两个库中的“GetSystemInfo”。然后问题就来了,一运行到KingStar_GetSystemInfo就segmentation fault

为了缩小问题范围,我把所有跟KingStar_GetSystemInfo无关的代码全部注掉,直到这个程序只剩上图中那三行。有意思的来了,

again。
此时这个程序跟上次成功运行只有一个区别:在编译链接时增加了一个LinuxDataCollect.so
我觉得这就是八字不合了,两个动态链接库居然不能共存?!
基于print的debug已经不行了
由请gdb登场

从trace back的信息#3可以看到,居然RSA_free()调用的是CTP的库LinuxDataCollect.so,应该这就是问题所在了。通过ldd命令可以知道libkcc.so 依赖了/lib/x86_64-linux-gnu/libcrypto.so.6,再用nm -D libcrypto.so.6 可以看到他也有RSA_free这个函数。所以应该是libkcc.so误用了LinuxDataCollect.so的RSA_free释放了错误的空间位置,导致段错误。
解决办法,动态调用动态链接库
主要用到dlfcn.h中的dlopen、dlsym和dlclose,链接时加上参数-ldl即可。改造后的代码如下:

虽然浪费了一天解决了一个个小小的问题,但对理解linux下的c++还是有收获的,主要运用到以下知识点:
- gdb
- ldd
- nm
- dlfcn.h
- 面向其他老程序员和百度的编程(这点最重要)
如果还有别的解决办法请教育我。