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

2023-11-21

我遇到了符号解析错误的问题。我的主程序使用 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_LAZY 替换为 RTLD_NOW 没有帮助。


I suspect两个全球符号之间存在冲突。一种解决方案是声明a在主程序中作为静态。或者,linux 手册页提到RTLD_DEEPBINDflag,仅适用于 Linux 的扩展,您可以将其传递给dlopen这将导致库更喜欢自己的符号而不是全局符号。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 dlopen 和 dlsym 以及 -fPIC 编译 C 程序 的相关文章

随机推荐

  • 对于登录 GET 还是 POST? [复制]

    这个问题在这里已经有答案了 我想知道我使用哪种 HTTP 方法来开发登录 API GET 还是 POST 我已经使用 post 方法在 PHP 中开发了登录 API 但是我的老板说 为什么你使用 POST 方法而不是 GET 方法 Alwa
  • 跨线程操作无效:从创建它的线程以外的线程访问控制“label1”[重复]

    这个问题在这里已经有答案了 可能的重复 为什么我会收到此错误 跨线程操作无效 控制 lbFolders 从创建它的线程以外的线程访问 我是 winforms 的新手 在我的代码中 我正在使用 for 循环更新进度条 现在我需要更新循环计数表
  • 在方法(Java 中)中改变对象参数是一种不好的做法吗?

    我有一个关于改变方法中的方法参数 它们是对象 的问题 我多次阅读和听到 在作为参数传入的方法中改变对象是一种不好的做法 例如 public void modifyList List list list add new Object 相反 应
  • jQuery 单击文档事件但忽略 div

    我正在使用 jQuery 制作在线幻灯片 我使用 document click 事件来检测用户何时单击页面 以了解何时显示幻灯片中的下一个项目符号点或移至下一页 我遇到的问题是我的工作让我在页面底部插入一个评论框 当有人单击评论框或保存评论
  • 使用 openssl 链接编译 Qt5 时出错

    我的头很快就会爆炸 我想用 openssl linked 编译 qt 以便 openssl 库链接到 qt 库中 我已经尝试了很多选项 编译时的输出始终是 ssl qsslcertificate openssl cpp In functio
  • Thymeleaf th:href 参数中的条件

    所以我的 Thymeleaf 模板中有一个元素 其中有一个如下所示的链接 th href search searchType parameter1 parameter1 parameter10 parameter10 根据目前的实施情况pa
  • 为什么在 JavaScript 中使用 {} != ( {} )?

    众所周知 是定义对象的更短方法 例如 用于数组 但现在我想知道为什么 计算结果为未定义 评估为 正确 对象 为什么 JavaScript 会有这样的行为 例如1等于 1 所以为什么 不等于 这是一个语法错误 语法错误 意外的标记 就是这样暧
  • 如何从目录中获取子文件夹中的文件

    您好 我必须从目录中的指定路径获取文件 这是我写的方法 但我没有从子文件夹中获取文件 Private void getfiles Directoryinfo info new Directoryinfo configurationmanag
  • 完全覆盖的代码的 EclEmma 覆盖率是否可以低于 100%?

    我只是编写了一些简单的示例代码来确保我正确安装了 EclEmma 我没有获得 100 的覆盖率 我不明白为什么 突出显示意味着它与类名有关 这是我的代码 以及相应的 JUnit 测试 EclEmma 突出显示了它 覆盖率结果显示 三个指令A
  • Tkinter grid_forget 正在清除框架

    from tkinter import from PIL import ImageTk Image root Tk root title Image Viewer def buttonforward image number global
  • 此按钮单击在 WPF MVVM 中如何工作?

    我开始研究WFM MVVM模式 但我不明白为什么会这样Buttonclick 无需绑定任何事件或操作即可工作 View
  • SwiftUI 自定义 TextField 与 UIViewRepresentable 与 ObservableObject 和推送视图的问题

    我创建了一个UIViewRepresentable包裹UITextField对于 SwiftUI 所以我可以例如当用户点击回车键时更改第一响应者 这是我的 UIViewRepresentable 我删除了第一响应者代码以保持简单 struc
  • 使用 ngTemplateOutlet 基于值而不是变量的动态模板

    我正在尝试模拟一组动态问题 想想一个测验 其中一个问题是多项选择 第二个是单一答案 第三个是是否 等等 使用 Angular 4 1 我认为使用 ngTemplateOutlet 进行模板化将是最好的方法 这个想法是我可以将所有复选框的样式
  • Haskell 中判断一棵树是否为二叉搜索树

    type BSTree a BinaryTree a data BinaryTree a Null Node BinaryTree a a BinaryTree a deriving Show flattenTree BinaryTree
  • 在字符串中使用变量

    在 PHP 中我可以执行以下操作 name John var Hello name gt Hello John C 中是否有类似的语言结构 我知道有String Format 但我想知道是否可以在不调用字符串上的函数 方法的情况下完成 在
  • 在 Windows 中安装 scipy 包

    我想安装 scipy 软件包 我知道这是一个重复的问题 但我已经尝试了所有这些 但没有找到合适的解决方案 当写这个 导入 scipy它执行成功 但是当我尝试这个时 import scipy spatial 我收到这条消息 Traceback
  • 如何更改导航栏标题位置?

    我已经设法使用自己的导航栏更改导航栏高度 但标题仍然居中 我希望它位于距左侧 72px 的位置 override func sizeThatFits size CGSize gt CGSize return CGSizeMake UIScr
  • 使用 XDocument 获取大写的 UTF-8

    我需要在我正在制作的 XML 文档的顶部有 XML 编码和版本XDocument 我有这个 但它是小写的 并且需要是大写的 我需要做什么 我使用以下方法声明一个新的 XML 文档XDocument名为 doc 的类 我使用以下命令将其保存到
  • 是否可以覆盖请求中的默认套接字选项?

    我使用优秀的 python 请求库为 REST API 编写了一个非常简单的客户端 一切工作都很好 我通过负载平衡器运行客户端 负载平衡器可以正常检测空闲的 tcp 连接并终止它们 我希望我的客户端使用一些与我的平台 Linux 上的默认选
  • 使用 dlopen 和 dlsym 以及 -fPIC 编译 C 程序

    我遇到了符号解析错误的问题 我的主程序使用 dlopen 加载共享库 并使用 dlsym 加载其中的符号 程序和库都是用 C 编写的 库代码 int a int b return b 1 int c int d return a d 1 为