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

标签 c linux gcc elf dlopen

我对错误的符号解析有疑问。我的主程序使用 dlopen 加载一个共享库,并使用 dlsym 从中加载一个符号。程序和库都是用 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的错误解析引起的。崩溃发生在调用a时,无论是从库还是从主程序调用(后者是通过注释掉主程序中调用c()的行获得的)。

调用c()本身没有出现问题,可能是因为c()不是库本身内部调用的,而a()既是库内部使用的函数,也是库的API函数。

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

用 RTLD_NOW 替换 RTLD_LAZY 没有帮助。

最佳答案

怀疑两个全局符号之间存在冲突。一种解决方案是在主程序中将 a 声明为静态的。或者,linux 联机帮助页提到了 RTLD_DEEPBIND 标志,这是一个仅限 linux 的扩展,您可以将其传递给 dlopen,这将导致库更喜欢自己的符号而不是全局符号。

关于使用带 -fPIC 的 dlopen 和 dlsym 编译 C 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10765320/

相关文章:

c++ - 获取 OpenCL 内核参数信息

c - 在 Mac OS Catalina 中,所有当前文档均因无法找到进程 ID 的 Mach 任务端口而失败,有什么建议吗?

在树莓派裸机编程中创建 C 库 stub

python - 无法访问/dev/mem。尝试以 root 身份运行

C - 初始化后填充结构 - 编译错误

c++ - 在 g++ 中使用 __attribute__ 的不平衡括号

c - GCC 为 Mersenne 程序输出非常大的可执行文件

c - 避免 C 宏中的冗余

linux - 为什么 Linux 中的 rm 命令可以在几秒钟内删除文件/目录,而在 FTP 中删除却非常慢

python - 如何最好地将数据流式传输到 IP 地址?