.o、.a 和 .so 文件有啥区别?

Posted

技术标签:

【中文标题】.o、.a 和 .so 文件有啥区别?【英文标题】:What is the difference between .o, .a, and .so files?.o、.a 和 .so 文件有什么区别? 【发布时间】:2015-07-23 01:18:33 【问题描述】:

我知道.o 是目标文件,.a 是静态库,.so 是动态库?它们的物理意义是什么?什么时候可以用,什么时候不能用?

【问题讨论】:

【参考方案1】:

.so 是共享库文件。 .a 是静态库文件。

您可以静态链接到 .a 库并在运行时动态链接和加载 .so 文件,前提是您以这种方式编译和链接。

.o 是目标文件(它们从 *.c 文件编译而来,可以链接以创建可执行文件、.a 或 .so 库。阅读更多关于它的信息here

【讨论】:

难道没有办法在运行时加载 .a 库吗?【参考方案2】:

.a 是一个“存档”。尽管存档可以包含任何类型的文件,但在 GNU 工具链的上下文中,它是一个目标文件库(其他工具链,尤其是在 Windows 上,出于相同目的使用 .lib,但这些格式通常不是通用的目的存档,并且通常特定于工具链)。可以从存档中提取单个目标文件,这基本上是链接器在使用库时所做的事情。

.o 是一个目标文件。这是编译为机器代码但不(通常)完全链接的代码 - 它可能具有对由单独编译生成的其他目标文件(在库中或单独)中定义的符号的未解析引用。目标文件包含元数据以支持与其他模块的链接,并且还可以选择用于源级符号调试(例如在 GDB 中)。其他工具链(通常在 Windows 上)使用扩展名 .obj 而不是 .o

.so 是一个共享对象库(或只是共享库)。这在程序启动时动态链接到可执行文件,而不是在构建时静态链接。它允许较小的可执行文件和一个对象库实例供多个可执行文件使用。操作系统 API 通常是共享库,并且出于许可原因,它们也经常在 GNU 中使用,例如将 LGPL 代码与闭源专有代码分开(我不是律师 - 我没有声称这种方法在任何特殊情况)。与.o.a 文件不同,应用程序使用的.so 文件必须在运行时系统上可用。其他系统(通常是 Windows)使用 .dll(动态链接库)用于相同目的。

了解.o 文件在.a 文件中链接之前 目标代码可能很有用,这样如果.o 文件满足符号分辨率,则任何库实现都将不被链接 - 允许您实质上用自己的库实现替换库实现,也允许库实现调用用户定义的代码 - 例如,GUI 框架可能会调用应用程序入口点。

【讨论】:

关于“.o文件在.a中的目标代码之前链接”,你的意思是不管你指定的顺序如何? @Pacerier:是的。在我遇到的每一个工具链中。这可能不是万无一失的。如果说您说有引用符号 ab 的代码,并且您在 .o 中定义 a 以覆盖库实现,但在库中 ab 都定义在同一个对象中模块然后链接库对象以解析 b 将拉入 a 与之前的定义冲突。如果库设计者打算覆盖符号,则应将符号声明为weak 以克服此类问题。或者,每个对象模块只有一个外部符号。【参考方案3】:

静态库是包含库的目标代码的档案,当链接到应用程序时,该代码被编译成可执行文件。

共享库的不同之处在于它们不会被编译成可执行文件。相反,动态链接器搜索一些目录以查找它需要的库,然后将其加载到内存中。多个可执行文件可以同时使用同一个共享库,从而减少内存使用和可执行文件大小。但是,还有更多文件要与可执行文件一起分发。您需要确保将库安装到用户系统中链接器可以找到的某个位置,静态链接可以消除此问题,但会导致可执行文件更大。

【讨论】:

However, there are then more files to distribute with the executable. 理想情况下正好相反。例如二进制包Linux 显然不会随身携带并尝试一遍又一遍地安装常用库的副本。它们标记了依赖项并要求用户安装它们。即使使用包管理器进行分发,人们通常也可以假设用户的系统已经具有所需的库,或者用户可以获得它们。主要是 Windows 经常使事情变得如此困难,以至于我们放弃并重新分发所有 DLL。哪个,呃……有点违背了动态链接的意义

以上是关于.o、.a 和 .so 文件有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

linux .o,.a,.so文件区别是什么

.o .a .so .dll的区别

C++学习(三八三).o .a .so .la .lo的区别

.a .o 和 .lo 文件之间的区别

macOS 上的 .so 和 .dylib 有啥区别?

matlab2015b和matlab2015a有啥区别