目标文件和共享目标文件之间的关系

2024-02-02

共享对象之间的关系是什么(.so) 文件和对象(.o) file?

你能通过例子解释一下吗?


假设您有以下 C 源文件,将其命名为name.c

#include <stdio.h>
#include <stdlib.h>

void print_name(const char * name)
{
    printf("My name is %s\n", name);
}

当你编译它时,用cc name.c你生成name.o。 .o 包含 name.c 中定义的所有函数和变量的已编译代码和数据,以及将其名称与实际代码关联的索引。如果您查看该索引,请说nm工具(在 Linux 和许多其他 Unix 上可用)您会注意到两个条目:

00000000 T print_name
         U printf

这意味着:.o 中存储了两个符号(函数或变量的名称,但不是类、结构或任何类型的名称)。第一个,标记为T实际上包含它的定义 in name.o。另一个,标有U仅仅是一个参考。代码为print_name可以在这里找到,但是代码printf不能。当您的实际程序运行时,它将需要找到所有引用的符号并在中查找它们的定义other目标文件,以便链接在一起形成完整的程序或完整的库。因此,目标文件是在源文件中找到的定义,转换为二进制形式,可用于放入完整的程序中。

您可以将 .o 文件一一链接在一起,但您不会这样做:它们通常有很多,而且它们是实现细节。您确实希望将它们全部收集到相关对象的捆绑包中,并具有易于识别的名称。这些捆绑包称为图书馆它们有两种形式:静态和动态。

A 静态库(在 Unix 中)几乎总是带有后缀.a(示例包括libc.a这是C核心库,libm.a这是 C 数学库)等等。继续您构建静态库的示例ar rc libname.a name.o。如果你跑nm on libname.a你会看到这个:

name.o:
00000000 T print_name
         U printf

正如您所看到的,它主要是一个带有索引查找的目标文件大表all里面的名字。就像目标文件一样,它包含每个中定义的符号.o以及它们所引用的符号。如果您要链接another.o(例如date.o to print_date),您会看到另一个与上面类似的条目。

如果将静态库链接到可执行文件中,它将整个库嵌入到可执行文件中。这就像链接所有个体一样.o文件。正如您可以想象的那样,这可能会使您的程序变得非常大,尤其是当您使用(就像大多数现代应用程序一样)大量库时。

A dynamic or 共享库后缀为.so。与它的静态类似物一样,它是一个大型目标文件表,引用所有已编译的代码。你会用它来构建它cc -shared libname.so name.o。看着与nm不过与静态库有很大不同。在我的系统上,它包含大约两打符号,其中只有两个是print_name and printf:

00001498 a _DYNAMIC
00001574 a _GLOBAL_OFFSET_TABLE_
         w _Jv_RegisterClasses
00001488 d __CTOR_END__
00001484 d __CTOR_LIST__
00001490 d __DTOR_END__
0000148c d __DTOR_LIST__
00000480 r __FRAME_END__
00001494 d __JCR_END__
00001494 d __JCR_LIST__
00001590 A __bss_start
         w __cxa_finalize@@GLIBC_2.1.3
00000420 t __do_global_ctors_aux
00000360 t __do_global_dtors_aux
00001588 d __dso_handle
         w __gmon_start__
000003f7 t __i686.get_pc_thunk.bx
00001590 A _edata
00001594 A _end
00000454 T _fini
000002f8 T _init
00001590 b completed.5843
000003c0 t frame_dummy
0000158c d p.5841
000003fc T print_name
         U printf@@GLIBC_2.0

共享库与静态库在一个非常重要的方面有所不同:它不会将自身嵌入到最终的可执行文件中。相反,可执行文件包含对该共享库的引用,该引用不是在链接时而是在运行时解析的。这有很多优点:

  • 您的可执行文件要小得多。它仅包含您通过目标文件显式链接的代码。外部库是引用,它们的代码不会进入二进制文件。
  • 您可以在多个可执行文件之间共享(因此得名)一个库的位。
  • 如果您非常注意二进制兼容性,则可以在程序运行之间更新库中的代码,并且程序将采用新库,而无需您进行更改。

有一些缺点:

  • 将程序链接在一起需要时间。对于共享库,部分时间会推迟到每次可执行文件运行时。
  • 这个过程比较复杂。共享库中的所有附加符号都是使库在运行时链接所需的基础设施的一部分。
  • 您面临着不同版本的库之间细微不兼容的风险。在 Windows 上这被称为“DLL 地狱”。

(如果您考虑一下,其中许多是程序使用或不使用引用和指针而不是直接将类的对象嵌入到其他对象中的原因。这个类比非常直接。)

好的,这是很多细节,我跳过了很多,例如链接过程的实际工作原理。我希望你能遵循它。如果没有要求澄清。

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

目标文件和共享目标文件之间的关系 的相关文章

随机推荐

  • 结束准备好的陈述

    我知道结束准备好的陈述是建议做的事情 https stackoverflow com questions 6631364 when to close prepared statement 但我有一个PHP像这样的脚本 sql SELECT
  • 限制搜索建议的数量,android

    使用具有自定义搜索建议的搜索界面时 是否有办法限制显示的建议数量 Thanks 其实很简单 首先在你的ContentProvider 定义一个变量来引用 public static final String LIMIT PARAMETER
  • 如何从 Windows 窗体 DateTimePicker 控件中仅获取日期值?

    我正在使用 C 代码构建一个应用程序 如何仅获取日期值DateTimePicker控制 我假设您指的是 winforms 应用程序中的日期时间选择器 在您的代码中 您可以执行以下操作 string theDate dateTimePicke
  • 为什么 selenium webdriver Firefox 不适用于非特权用户?

    我正在尝试使用 selenium 在 python 的 Django 视图中创建屏幕截图 如果我在 root 下启动 selenium firefox webdriver 运行良好 但是 当我尝试使用非超级用户运行它时 它在尝试实例化驱动程
  • java.net.SocketTimeoutException:读取超时

    我有一个具有客户端服务器架构的应用程序 客户端 将 Java Web Start 与 Java Swing AWT 结合使用 sert 使用 HTTP 服务器 Servlet 与 雄猫 通信是通过对象的序列化进行的 创建一个 ObjectO
  • 描边宽度变换 (SWT) 实现(Java、C#...)[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我最近发现了笔划宽度变换 如以下研究论文中所述 使用笔划宽度变换检测自然场景中的文本 https ie
  • 如何在 Angular 2 中进行全局搜索?

    我是 angular2 的新开发人员 我想在 json 对象数组中进行全局搜索 例如 这个数组 invoiceList invoiceNumber 1234 invoiceSupplier test invoiceStatus Import
  • 使用 jquery.validation equalTo( other ) 确保“Sunday”是输入值

    RE http docs jquery com Plugins Validation http docs jquery com Plugins Validation 我正在设置一个简单的联系表单 并希望使用 测验 作为简单的垃圾邮件防护 因
  • 根据每个 Pod 的活动连接数扩展 GKE Pod

    我有一个正在运行的 GKE 集群 其中包含使用目标 CPU 利用率指标的 HPA 这没问题 但 CPU 利用率对我们来说并不是最佳的扩展指标 分析表明 活动连接计数是一般平台负载的良好指标 因此 我们希望将其视为我们的主要扩展指标 为此 我
  • 转换为 hls 时,FFmpeg 烧录的字幕不同步

    我有一个刻有字幕的文件 并且它们完全同步 这是文件 https 983yqbz442 s3 amazonaws com little mermaid captions mp4 https 983yqbz442 s3 amazonaws co
  • Java代码减少行与行之间的垂直间距

    我正在创建一个包含一些内容的 PDF 我的要求是在创建 PDF 时减少行间距 以便在单页中容纳更多行数 如何减少行与行之间的间距 Document document null PdfWriter getInstance document n
  • 使用单个 log4j2 xml 文件配置 log4j2 和 log4j

    我已将应用程序迁移到 log4j 2 并通过 log4j2 xml 配置它 但是 我使用的一些库依赖于 log4j 1 如果我使用以下命令运行应用程序 Dlog4j configurationFile path to log4j2 xml
  • R 中的模式匹配和替换

    我对正则表达式一点也不熟悉 想在 R 中进行模式匹配和替换 我想更换图案 1 2在向量中 original c 1 2 10 11 向量的每个值vec c 1 2 我正在寻找的结果是以下向量 c 1 2 10 11 我不知道该怎么做 我尝试
  • Laravel 5.3 使用 url 中的图像进行干预/图像 NotReadableException

    如何处理以下错误 以便我的脚本在出现以下错误时不会停止工作发生异常 AbstractDecoder php 第 302 行中的 NotReadableException 图像源不是 可读的 我尝试使用以下内容 file 是图像的 url R
  • 获取单词和空格字符串中的第一个单词 - 空格前的子串第一个单词

    我有一个包含单词和空格的字符串 2h 3m 1s 我想提取2h脱离它 所以在第一个空格之前得到所有的东西 var date 1 340d 1h 15m 52s I want to extract 1 340d 这样做的最佳实践是什么 什么子
  • Firefox 实时 http 标头,缓存控制后的花括号:无缓存

    我正在设置一个 php cURL 脚本来复制我在实时标题中看到的内容 这是一个例子 Cache Control no cache username email protected cdn cgi l email protection pas
  • mysql 在查找和插入时将整数截断为奇怪的数字

    我在 php 中使用 Laravel 的 Eloquent 来插入和查找记录 发生的情况是 当我插入一个整数时 这里是 1001094515039 它会将其更改为 367135071 并将其存储在字段中 字段类型是 Bigint 长度为 2
  • Python 守护进程打包最佳实践

    我有一个用 python 编写的工具 通常应该作为守护进程运行 打包此工具进行分发的最佳实践是什么 特别是应如何处理设置文件和守护进程可执行文件 脚本 相关地 是否有任何通用工具可用于设置守护进程以在启动时运行 以适合给定的平台 即init
  • 如何在flutter插件中导入AAR文件?

    我正在使用 flutter 插件并想要导入 aarandroid 项目中的插件部分 我尝试打开 android 项目并导入 aar通过导入模块来项目 将其包含在setting gradle并将其添加到依赖项中build grade 就像任何
  • 目标文件和共享目标文件之间的关系

    共享对象之间的关系是什么 so 文件和对象 o file 你能通过例子解释一下吗 假设您有以下 C 源文件 将其命名为name c include