c++ - 静态库中的符号有时会链接到可执行文件中,有时不会

标签 c++ linux gcc

我有一个静态库,它是使用 g++ 从 linux 上的许多 cpp 文件生成的。一个头文件包含一个实现工厂模式的类

头文件中的伪代码如下

class Factory
{
public:
    static Factory& instance();
    Base * create(const std::string& name);
    template<class T>
      void register_class(const std::string& name);
}

template <class T>
class FactoryRegister
{
public:
    FactoryRegister(const std::string& name)
    {
       Factory::instance().register_class<T>(name);
    }
}

Factory 的 cpp 文件有实现。在另一个 cpp 文件 Derive.cpp 中,有一个类我想注册到 Factory 中。我定义了一个全局变量来执行此操作。代码如下

FactoryRegister<Derive> g_register_derive("derive");

所有这些文件都编译成一个静态库并链接到一个可执行文件。

我的理解是,由于 g_register_derive 未被任何代码引用,因此不应将其链接到可执行文件中,除非提供了 whole-archive 选项。

奇怪的是,如果我将 g_register_derive 放在 Derive.cpp 中,这个符号确实没有链接到可执行文件中。但是如果我把 g_register_derive 放在 Factory.cpp 中,它就会链接到可执行文件中。

我用nm验证了结果,还有一行代码调用Factory::instance().create("Derive")也可以用来检查g_register_derive是否是链接与否。

当然,如果我提供了 whole-archive 选项,g_register_derive 将始终链接到可执行文件中。

最佳答案

参见 the Stackoverflow tag wiki about static-libraries 了解与静态库的链接,尤其是默认情况下,仅当链接器需要<时,静态库中的目标文件 libx.a(p.o) 才会被提取并链接到程序中/em> 它。

如果链接器需要链接一个存档成员 libx.a(p.o) 以便 解析对该目标文件中定义的符号 foo 的一些先前引用, 然后是在 libx.a(p.o) 中定义的任何其他符号 bar 的定义 也链接到程序中——因为它是目标文件的一部分——是否 bar 是否被程序引用。

因此,如果您在编译的源文件 p.cpp 中定义 g_register_derivep.o 并存档为 libx.a(p.o),您的应用程序需要链接 libx.a(p.o) 出于任何原因,则默认情况下1 g_register_derive 变为 在你的程序中定义。

如果将 g_register_derive 的定义移动到 q.cpp,编译存档为libx.a(q.o),以及您的应用程序 不需要出于任何原因需要链接libx.a(q.o),然后g_register_derive 未在您的程序中定义。


[1] 使用非默认编译和链接选项,您可以删除定义 程序中的未使用 符号。参见 How to remove unused C/C++ symbols with GCC and ld?以及接受的答案。

关于c++ - 静态库中的符号有时会链接到可执行文件中,有时不会,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54126641/

相关文章:

c++ - 为什么基于 int 的访问对 std::get(std::tuple) 不起作用?

c++ - 在 CreateProcess 之后调用 GetModuleFileNameEx 时出现 ERROR_INVALID_HANDLE

c - C中函数 "localtime"的异常行为

linux - 如何在 Linux 64 位上运行 Rebol 脚本

c++ - 用于使用 g++ 编译的 .vimrc 脚本

c++ - 将 C++ 字符数组传递给 Fortran

C++ 构造函数中的循环指针注入(inject)

linux - Linux 中最好的代码比较工具是什么?

linux - 在 CentOS7.4 的 AARCH64 平台上首选哪个 GCC 版本?

c++ - 匿名命名空间在这里导致 undefined reference - 在那里工作