c++ - 链接静态库时静态对象的初始化

标签 c++ static-libraries ld

在另一个共享库中声明的静态对象的初始化规则是什么?例如,请考虑以下内容:

文件 X.hpp:

struct X {
   X ();
   static X const s_x;
};

struct Y {
   Y (X const &) {}
};

文件 X.cpp:

#include "X.hpp"
#include <iostream>

X::X ()
{
   std::cout << "side effect";
}

X const X::s_x;

我在静态库 libX.a 中编译了 X.cpp,并尝试链接以下可执行文件(文件 main.cpp):

#include "X.hpp"

int main ()
{
     (void)X::s_x;  // (1)
     X x = s_x;     // (2)
     Y y = s_x;     // (3)
 }

只有 (1) 或 (2),什么也不会发生。但是如果我添加(3),静态对象被初始化(即打印“副作用”)。 (我使用 gcc 4.6.1)。

有没有办法预测这里会发生什么?

我不明白指令 (2) 为何不强制 X::s_x 对象默认构造,而 (3) 却强制构造。

编辑:构建命令:

g++ -c X.cpp
g++ -c main.cpp
ar rcs libX.a X.o
g++ -o test main.o -L. -lX

最佳答案

默认情况下,在许多平台上,如果您的程序没有引用静态库中给定目标文件中的任何符号,则整个目标文件(包括静态初始值设定项)将被删除。因此链接器忽略了 libX.a 中的 X.o,因为它看起来未被使用。

这里有几个解决方案:

  1. 不要依赖静态初始化器的副作用。这是最便携/最简单的解决方案。
  2. 通过以编译器无法识别的方式引用虚拟符号(例如将地址存储到外部可见的全局变量中),在每个文件中引入一些虚假的依赖关系。
  3. 使用一些特定于平台的技巧来保留相关对象。例如,在 Linux 上,您可以使用 -Wl,-whole-archive a.o b.a -Wl,-no-whole-archive

关于c++ - 链接静态库时静态对象的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7327741/

相关文章:

c++ - 我如何检测两个文件条目是否引用与 Qt 相同的物理文件系统?

c++ - 写入文件时,fprintf 与 printf 不同吗?

C++ libxml xmlNode->children

linux - 程序错误 : ./程序 : error while loading shared libraries: lib<xxx>. 所以:无法打开共享对象文件:没有这样的文件或目录

c - GCC (NOLOAD)-指令导致错误的内存映射

c++ - Windows 上 Mingw 的 DLL 依赖项

iOS 制作通用库 - 适用于 i386 和 arm7

c++ - 声明全局变量,在方法中初始化

xcode - 在 Xcode4 中将静态库项目作为模块管理,如 iOS 项目上的框架

c - gcc -c 和 ld : exec No such file or directory