背景
前不久在调试一个与导出符号相关的bug,问题大概如此:
模块A.so在堆上构造了一个对象即 CTest *one = new CTest; , CTest在A.so定义,后来使用one->AMemFunc();,即调用一个成员函数时崩溃。原来在另一个模块B.so(比A.so先加载)中,也有一个同名的CTest定义,但是却没有一个叫AMemFunc的成员函数,因此崩溃。
那为什么A.so的CTest会被解析到B.so呢?
全局符号介入
这种一个共享对象里面的全局符号被另一个共享对象的同名全局符号覆盖的现象又被称为共享对象全局符号介入(Global Symbol Interpose)。对于全局符号介入这个问题,linux下的动态连接器是这样处理的:它定义了一个规则,那就是当一个符号需要被加入全局符号表时,如果相同的符号名已经存在,则后加入的符号被忽略。
其实,在上述的情形里,B.so的CTest是不需要导出的,GCC编译的so