简体   繁体   English

在链接静态库时初始化静态对象

[英]initialisation of static object when linking against a static library

What are the rules for initialisation of static object declared in another shared library? 初始化在另一个共享库中声明的静态对象的规则是什么? For instance, consider the following: 例如,请考虑以下事项:

file X.hpp: 文件X.hpp:

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

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

file X.cpp: 文件X.cpp:

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

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

X const X::s_x;

I compiled X.cpp in a static library libX.a , and I tried to link the following executable against it (file main.cpp): 我在静态库libX.a编译了libX.a ,并尝试将以下可执行文件链接到它(文件main.cpp):

#include "X.hpp"

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

with only (1) or (2), nothing happens. 只有(1)或(2),没有任何反应。 But if I add (3), the static object is initialised (ie "side effect" is printed). 但是如果我添加(3),则初始化静态对象(即打印“副作用”)。 (I use gcc 4.6.1). (我使用gcc 4.6.1)。

Is there any way to predict what will happen here? 有没有办法预测这里会发生什么?

I don't understand how the instruction (2) does not force the X::s_x object to be default-constructed, whereas (3) does. 我不明白指令(2)如何不强制X::s_x对象是默认构造的,而(3)则不然。

EDIT: build commands: 编辑:构建命令:

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

By default on many platforms, if your program doesn't reference any symbols from a given object file in a static library, the whole object file (including static initializers) will be dropped. 默认情况下,在许多平台上,如果您的程序没有引用静态库中给定目标文件的任何符号,则将删除整个目标文件(包括静态初始化程序)。 So the linker is ignoring Xo in libX.a because it looks like it is unused. 所以链接器忽略了libX.a中的Xo,因为它看起来像是未使用过的。

There are a few solutions here: 这里有一些解决方案:

  1. Don't depend on the side-effects of static initializers. 不要依赖静态初始化器的副作用。 This is the most portable/simple solution. 这是最便携/简单的解决方案。
  2. Introduce some fake dependency on each file by referencing a dummy symbol in a way the compiler will not see through (like storing the address into a externally-visible global). 通过以编译器无法看到的方式引用虚拟符号(例如将地址存储到外部可见的全局中)来引入对每个文件的一些虚假依赖。
  3. Use some platform-specific trick to retain the objects in question. 使用一些特定于平台的技巧来保留有问题的对象。 For example, on Linux you can use -Wl,-whole-archive ao ba -Wl,-no-whole-archive . 例如,在Linux上,您可以使用-Wl,-whole-archive ao ba -Wl,-no-whole-archive

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM