我遇到了错误的符号解析问题。我的主程序用dlopen加载一个带有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 %d d is %d\n",b,d);
return 0;
}
如果程序未使用-fPIC编译,则一切正常,但在使用-fPIC编译程序时,它会因分段错误而崩溃。调查导致发现崩溃是由于符号a的错误解决。无论是从库还是主程序(后者是通过在主程序中注释掉调用c()的行获得的),都会在调用a时发生崩溃。
调用c()本身时不会出现问题,可能是因为c()不是由库本身内部调用,而a()既是库内部使用的函数,也是库的API函数。
编译程序时,一个简单的解决方法是不使用-fPIC。但这并不总是可行的,例如当主程序的代码必须在共享库本身时。另一种解决方法是将指针重命名为其他功能。但我找不到任何真正的解决方案。
用RTLD_NOW替换RTLD_LAZY无济于事。
答案 0 :(得分:2)
我怀疑两个全局符号之间存在冲突。一种解决方案是将主程序中的a
声明为静态。或者,linux手册页提到RTLD_DEEPBIND
标志,这是一个仅限linux的扩展,您可以将其传递给dlopen
,这将使库更喜欢自己的符号而不是全局符号。
答案 1 :(得分:0)
似乎这个问题可以在另外一个案例中发生(就像我一样)。我有一个程序和几个动态链接的库。当我尝试添加一个时,我使用了一个来自 static lib(我也是)的函数。而且我忘了将这个静态库添加到联动列表中。 Linker没有对此提出警告,但程序因分段错误错误而崩溃。
也许这对某人有帮助。
答案 2 :(得分:0)
FWIW,当我编译为C ++并忘记名称修饰时,遇到了类似的问题。一种解决方案是使用extern "C"
。