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:
struct X {
X ();
static X const s_x;
};
struct Y {
Y (X const &) {}
};
file 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):
#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. But if I add (3), the static object is initialised (i.e. "side effect" is printed). (I use 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.
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 X.o in libX.a because it looks like it is unused.
There are a few solutions here:
- Don't depend on the side-effects of static initializers. This is the most portable/simple solution.
- 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).
- Use some platform-specific trick to retain the objects in question. For example, on Linux you can use
-Wl,-whole-archive a.o b.a -Wl,-no-whole-archive
.
精彩评论