使用dlopen和dlsym使用-fPIC编译C程序

我有一个错误的符号parsing的问题。 我的主程序用dlsym加载了一个dlopen共享库和一个来自它的符号。 程序和库都是用C库代码编写的

int a(int b) { return b+1; } int c(int d) { return a(d)+1; } 

为了使它在64位机器上工作,-fPIC在编译时传递给gcc

该计划是:

 #include <dlfcn.h> #include <stdio.h> int (*a)(int b); int (*c)(int d); int main() { void* lib=dlopen("./libtest.so",RTLD_LAZY); a=dlsym(lib,"a"); c=dlsym(lib,"c"); int d = c(6); int b = a(5); printf("b is %dd is %d\n",b,d); return 0; } 

如果程序不是用-fPIC编译的话,一切运行正常,但是当用-fPIC编译程序时,程序崩溃时会出现分段错误。 调查发现,坠机是由于符号a的错误parsing。 当调用a时会发生崩溃,无论是从库还是主程序(后者通过在主程序中注释掉调用c()的行来获得)。

调用c()本身时不会出现问题,可能是因为c()不是由库本身在内部调用的,而a()既是库内部使用的函数又是库的API函数。

编译程序时,一个简单的解决方法是不使用-fPIC。 但是这并不总是可能的,例如当主程序的代码必须在共享库中时。 另一个解决方法是将指针重命名为另一个函数。 但是我找不到任何真正的解决办法。

用RTLD_NOW代替RTLD_LAZY不会有帮助。

怀疑两个全球符号之间有冲突。 一种解决方案是在主程序中声明a静态的。 或者,linux手册页提到了RTLD_DEEPBIND标志,它是一个仅用于Linux的扩展,您可以将其传递给dlopen ,这会使库在全局符号上使用自己的符号。

似乎这个问题可以发生在另一个案件(像我一样)。 我有一个程序和一对动态链接的库。 当我试图添加一个更多的时候,我用一个静态库(我也是)在它的功能。 我忘了添加到链接列表这个静态库。 Linker并没有警告我这个,但是程序被分段错误错误粉碎。

也许这会帮助别人。