静态库中的符号有时会链接到可执行文件,有时不会
Posted
技术标签:
【中文标题】静态库中的符号有时会链接到可执行文件,有时不会【英文标题】:symbols in static library sometimes got linked into executable, sometimes not 【发布时间】:2019-01-10 10:27:59 【问题描述】:我有一个静态库,它是使用 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);
工厂的 cpp 文件有实现。在另一个 cpp 文件 Derive.cpp 中,有一个我想注册到工厂的类。我定义了一个全局变量来做到这一点。代码如下
FactoryRegister<Derive> g_register_derive("derive");
所有这些文件都编译成一个静态库并链接到一个可执行文件。
我的理解是,由于任何代码都没有引用 g_register_derive,因此除非提供了整体存档选项,否则不应将其链接到可执行文件中。
奇怪的是,如果我把 g_register_derive 放在 Derive.cpp 中,这个符号确实没有链接到可执行文件中。但是如果我将 g_register_derive 放在 Factory.cpp 中,它就会链接到可执行文件中。
我用nm验证结果,还有一行代码调用Factory::instance().create("Derive")
也可以用来检查g_register_derive是否链接。
当然,如果我提供了整体存档选项,g_register_derive 将始终链接到可执行文件中。
【问题讨论】:
【参考方案1】:见the *** tag wiki about static-libraries
了解与静态库的链接,尤其是默认情况下,仅当链接器需要时,才会提取静态库中的目标文件libx.a(p.o)
并将其链接到程序中。
如果链接器需要链接存档成员 libx.a(p.o)
以便
解决对该目标文件中定义的符号foo
的某些先前引用,
然后定义在libx.a(p.o)
中定义的任何其他符号bar
也链接到程序中 - 因为它是该目标文件的一部分 - 是否
bar
是否被程序引用。
所以,如果你在编译的源文件p.cpp
中定义g_register_derive
到p.o
并归档为libx.a(p.o)
,您的应用程序需要链接
libx.a(p.o)
出于任何原因,那么默认情况下1g_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? 和接受的答案。
【讨论】:
谢谢,这个问题困扰我好几天了。以上是关于静态库中的符号有时会链接到可执行文件,有时不会的主要内容,如果未能解决你的问题,请参考以下文章