本文主要记录了个人在实际开发过程中遇到的坑,以及解决办法,后续如有增加会持续更新。
1.问题1
描述
项目需要开发一个共享库libA.so,在源代码里使用dlopen动态加载库第三方库libB.so时,导出了其中需要用到的函数符号,但是某些函数需要使用库中定义的全局变量g_nVar_Lib,开发者没有仔细考虑这一点,采用了
extern int g_nVar_Lib;
声明了这个全局变量,保证了libA.so顺利编译通过,并生成了指的库。但后来在可执行程序中使用libA.so,也是采用dlopen的方式,结果dlopen无论怎样传参加载库都失败。
原因
使用dlerror查看错误原因是“libA.so中存在未定义的符号g_nVar_Lib”,问题就相当明了了,采用动态加载的方式,程序运行到dlopen的时候会解析LibA.so中的全局变量,此时g_nVar_Lib确实没有定义,因为只有在加载libB.so后才能解析该符号,那可执行程序必然会报错。
解决方案
方法一:需要使用第三方库中全局变量的时候,要用dlsym将该全局变量的符号解析出来,方法和解析函数是一样的,需要事先定义好变量的指针。
方法二:动态加载改为静态加载的方式,即在编译libA.so时,使用-lB,这样将符号解析的任务交给链接器,可执行程序在dlopen,共享库A之后,链接器会自动去装载B库,完成符号解析和重定位任务。
2.问题2
描述
开发的可执行程序A,采用静态链接的方式依赖libB.so,但是由于粗心,将本来并不需要的libC.so引入了进来,且先于B库引入,大致是这么个情形
-lC,-lB
结果在实际运行时程序A没有按照预想的那样去执行,出现了奇奇怪怪的问题。
原因
B库是由第三方厂家开发,里面的具体实现不得而知,链接器在加载C库后使用了C库中的全局符号,在加载B库后,原本B库使用的全局符号得不到解析因为已经在C中解析了同名的全局符号,这样就会出现问题,这种问题会是灾难性的,也不容易排查。
解决方案
非必须的库一定不要无故引入;自己封装的库也要控制符号的可见性,同时控制编译参数-Wl,-Bsymbolic优先采用自己库内的全局符号。