链接静态库时链接器可以省略目标文件吗?

Posted

技术标签:

【中文标题】链接静态库时链接器可以省略目标文件吗?【英文标题】:can linker omit object file when linking static lib? 【发布时间】:2010-12-05 16:39:49 【问题描述】:

我有一个静态库 (lib.a) 和一个链接到它的程序。该库没有任何入口点,在使用它之前总是会被调用,但我需要在程序的早期执行一段代码(最好在 main() 开始之前)。因此我想我会使用我自己的类的静态变量。我添加了包含以下内容的新源文件:

#include <MyClass.h>
static MyClass myVar;

然后 MyClass 的构造函数将执行我的代码。当我链接 lib.a 并尝试对其执行“nm”时,我得到了 myVar 存在的信息。但是,当我链接我的程序并在其上尝试“nm”时,我看不到 myVar。当我将这段代码放入现有文件时,该符号在最终的可执行文件中可见。这是为什么?在这种情况下,链接器可以从 lib.a 库中省略目标文件吗?我知道该变量不是从外部引用的(它不能是静态的),但它应该自己执行代码,因此我不明白为什么要删除它。

如果有什么不同,我会使用一些旧的 SunPro 编译器。

【问题讨论】:

编写依赖于全局变量初始化的代码是个坏主意。更好的事情是如何做得更好。 @ybungalobil:它可能很有用;例如单元测试。 (这是大多数 C++ 单元测试框架处理自动测试注册的方式)。 @Tomasz:您使用的是什么编译器/平台? @Billy:它可能有用,但前提是最多有一个组件依赖它。否则你会得到非常糟糕的事情(初始化顺序未定义)。他还写道,他使用“旧的 SunPro 编译器”。 @ybungalobill:我知道它有问题——但是,我的意思是这并不总是一个坏主意。是的,有一些注意事项需要注意,但这并不意味着没有人应该使用该构造。 【参考方案1】:

从技术上讲,应该强制链接器在编译程序时包含该目标文件。但是,许多编译器对此的支持存在缺陷,例如MSVC++。在主程序的某处添加外部引用应该强制包含该目标文件。

另请注意,在nm 的情况下,您的静态初始化程序可能已内联,因此该符号不需要存在于您的最终二进制文件中。在你的静态文件中尝试一些有副作用的东西(比如std::cout 语句),并确保它在责怪编译器之前不会运行:)

【讨论】:

我知道它不起作用,这就是我开始使用 nm 进行调查的原因。感谢您提供它应该正常工作的信息,但很高兴知道它是由 C++/其他标准定义还是仅在其他编译器中工作? @Tomasz:C++ 标准没有说明如何组装最终的二进制文件。 (即标准不知道静态库或动态库的存在)这是因为标准被编写为机器中立的,并且这样的库在许多架构上是不可能的(特别是那些分离代码和数据的架构)【参考方案2】:

事实证明,链接器所做的是非常标准的(我不是指 C++ 标准,只是一般的观察者行为),您可以解决它。在 GNU ld 中,它是 --whole-archive 选项,在我的 Sun 工具中,它是 -z allextract。对于我的项目,这实际上并没有按预期工作,所以我使用了一些带有弱符号的魔法 -z weakextract 来实现我想要的。

【讨论】:

以上是关于链接静态库时链接器可以省略目标文件吗?的主要内容,如果未能解决你的问题,请参考以下文章

linux 静态链接和动态链接

Linux静态库生成指南

链接器如何使用静态库解析引用

我们可以静态链接动态 C 库吗?

静态链接

链接