为什么使用共享库时对象和库的顺序不影响链接?

2023-12-03

我有以下源代码:

  • foo.h

    void foo();
    
  • foo.cpp

    #include "foo.h"
    #include <iostream>
    
    void foo(){
        std::cout << "This is foo" << std::endl;
    }
    
  • main.cpp:

    #include "foo.h"
    
    int main(){
        foo();
    
        return 0;
    }
    

然后我运行以下命令来生成 foo.cpp 的静态版本和共享版本:

g++ -c -fPIC foo.cpp
ar rvs libfoo.a foo.o
g++ -shared -o libfoo.so foo.o
g++ -c main.cpp

如果我尝试使用静态生成可执行文件libfoo.a and main.o,目标文件和库文件的顺序很重要:

g++ main.o libfoo.a -o main  # works
g++ libfoo.a main.o -o main  # fails with undefined references to `foo()`

正如中所解释的这个帖子,顺序很重要。

但是,如果我尝试使用共享构建可执行文件libfoo.so and main.o,目标文件和库文件的顺序不再重要:

g++ main.o libfoo.so -o main   # works
g++ libfoo.so main.o -o main   # also works without errors

这是否意味着当我们链接目标文件和共享库时顺序并不重要?或者这只是一个特例或我不知道的巧合?

上述代码和命令在以下平台测试:

  • Linux:CentOS 7.4
  • gcc:7.3.1 或 4.8.5(均已测试)

正如这篇文章中所解释的,顺序很重要。

更详细的解释是here.

订单很重要传统的UNIX 链接器,但最近 LLD 决定打破传统,记录存档库中符号的可用性,即使它们没有立即引用。

目前,Linux 上提供三种不同的链接器:原始 BFD 链接器、Gold 链接器(大约 2008 年)和 LLD(大约 2019 年)。

使用“正确”的顺序对所有三个都成功(自然)。

使用“错误”的顺序:g++ libfoo.a main.oBFD 和 Gold 失败,但 LLD 成功:

g++ libfoo.a main.o -fuse-ld=lld && echo $?
0

但是,如果我尝试使用共享的 libfoo.so 和 main.o 构建可执行文件,则目标文件和库文件的顺序不再重要

The reason it doesn't matter is that linkers treat .so similarly to how they treat .o. In particular, there is no need to "pull out parts" of .so -- you get the entire .so (just as you would1 if you used foo.o)

所以当你链接时g++ libfoo.so main.o,这个链接是almost相当于使用g++ foo.o main.o,并且前一个命令中的顺序无关紧要,其原因与后一个命令中的顺序无关紧要相同。


1Building with -ffunction-sections and using --gc-sections notwithstanding.

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

为什么使用共享库时对象和库的顺序不影响链接? 的相关文章

  • 当我在组合框中选择一个项目时,如何防止 TextChanged 事件?

    我有一个TextChanged http msdn microsoft com en us library system windows forms control textchanged aspx我的事件ComboBox http msd
  • 如何从 C# 中的 dataTable.Select( ) 查询中删除单引号?

    所以我有一个经销商名称列表 我正在我的数据表中搜索它们 问题是 一些傻瓜必须被命名为 Young s 这会导致错误 drs dtDealers Select DealerName dealerName 所以我尝试替换字符串 尽管它对我不起作
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 使用valgrind进行GDB远程调试

    如果我使用远程调试gdb我连接到gdbserver using target remote host 2345 如果我使用 valgrind 和 gdb 调试内存错误 以中断无效内存访问 我会使用 target remote vgdb 启动
  • 打印大型 WPF 用户控件

    我有一个巨大的数据 我想使用 WPF 打印 我发现WPF提供了一个PrintDialog PrintVisual用于打印派生的任何 WPF 控件的方法Visual class PrintVisual只会打印一页 因此我需要缩放控件以适合页面
  • WebBrowser.Print() 等待完成。 。网

    我在 VB NET 中使用 WebBrowser 控件并调用 Print 方法 我正在使用 PDF 打印机进行打印 当调用 Print 时 它不会立即启动 它会等到完成整个子或块的运行代码 我需要确保我正在打印的文件也完整并继续处理该文件
  • C++ new * char 不为空

    我有一个问题 我在 ASIO 中开发服务器 数据包采用尖头字符 当我创建新字符时 例如char buffer new char 128 我必须手动将其清理为空 By for int i 0 i lt 128 i buffer i 0x00
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐