Linux 使用带有 -fPIC 的 dlopen 和 dlsym 编译 C 程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10765320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Compile C program using dlopen and dlsym with -fPIC
提问by user377486
I am having a problem about a wrong symbol resolution. My main program loads a shared library with dlopen and a symbol from it with dlsym. Both the program and the library are written in C. Library code
我遇到了错误的符号解析问题。我的主程序使用 dlopen 加载一个共享库,并使用 dlsym 从中加载一个符号。程序和库都是用C编写的。 库代码
int a(int b)
{
return b+1;
}
int c(int d)
{
return a(d)+1;
}
In order to make it work on a 64-bit machine, -fPIC is passed to gcc when compiling.
为了使其在 64 位机器上工作,编译时将 -fPIC 传递给 gcc。
The program is:
该计划是:
#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;
}
Everything runs fine if the program is NOT compiled with -fPIC, but it crashes with a segmentation fault when the program is compiled with -fPIC. Investigation led to discover that the crash is due to the wrong resolution of symbol a. The crash occurs when a is called, no matter whether from the library or the main program (the latter is obtained by commenting out the line calling c() in the main program).
如果程序不是用 -fPIC 编译的,一切都运行良好,但是当程序用 -fPIC 编译时,它会因分段错误而崩溃。调查导致发现崩溃是由于符号a的错误解析。无论是从库调用还是从主程序调用 a 都会发生崩溃(后者是通过注释掉主程序中调用 c() 的行获得的)。
No problems occur when calling c() itself, probably because c() is not called internally by the library itself, while a() is both a function used internally by the library and an API function of the library.
调用c()本身没有问题,可能是因为c()不是库本身内部调用的,而a()既是库内部使用的函数,也是库的API函数。
A simple workaround is not use -fPIC when compiling the program. But this is not always possible, for example when the code of the main program has to be in a shared library itself. Another workaround is to rename the pointer to function a to something else. But I cannot find any real solution.
一个简单的解决方法是在编译程序时不使用 -fPIC。但这并不总是可行的,例如当主程序的代码必须在共享库本身中时。另一种解决方法是将指向函数 a 的指针重命名为其他内容。但我找不到任何真正的解决方案。
Replacing RTLD_LAZY with RTLD_NOW does not help.
用 RTLD_NOW 替换 RTLD_LAZY 没有帮助。
采纳答案by zvrba
I suspectthat there is a clash between two global symbols. One solution is to declare a
in the main program as static. Alternatively, the linux manpage mentions RTLD_DEEPBIND
flag, a linux-only extension, which you can pass to dlopen
and which will cause library to prefer its own symbols over global symbols.
我怀疑两个全局符号之间存在冲突。一种解决方案是a
在主程序中声明为静态。或者,linux 联机帮助页提到了RTLD_DEEPBIND
标志,这是一个仅限 linux 的扩展,您可以传递给它dlopen
,这将导致库更喜欢自己的符号而不是全局符号。
回答by Serge Roussak
It seems this issue can take place in one more case (like for me). I have a program and a couple of a dynamically linked libs. And when I tried to add one more I used a function from a staticlib (my too) in it. And I forgot to add to linkage list this static lib. Linker was not warn me about this, but program was crushing with segmentation fault error.
似乎这个问题可以在另一种情况下发生(就像我一样)。我有一个程序和几个动态链接的库。当我尝试再添加一个时,我在其中使用了静态库(我的也是)中的一个函数。我忘了将这个静态库添加到链接列表中。链接器没有就此警告我,但程序因分段错误错误而崩溃。
Maybe this will help for someone.
也许这会对某人有所帮助。
回答by B?a?ej Czapp
FWIW, I ran into a similar problem when compiling as C++ and forgetting about name mangling. A solution there is to use extern "C"
.
FWIW,我在编译为 C++ 并忘记名称修改时遇到了类似的问题。有一个解决方案是使用extern "C"
.