Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 967
Nicolas Grebille Avatar asked Sep 07 '11 00:09

Nicolas Grebille


People also ask

How do you initialize a static object?

For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator (::), then the variable name. Now we can assign some value.

What happens when you link a static library?

Static linking increases the file size of your program, and it may increase the code size in memory if other applications, or other copies of your application, are running on the system. This option forces the linker to place the library procedures your program references into the program's object file.

What is meant by static initialization of objects?

You initialize a static object with a constant expression, or an expression that reduces to the address of a previously declared extern or static object, possibly modified by a constant expression.

Which operator is used for static initialization?

As static variables are initialized only once and are shared by all objects of a class, the static variables are never initialized by a constructor. Instead, the static variable should be explicitly initialized outside the class only once using the scope resolution operator (::).


1 Answers

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:

  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 a.o b.a -Wl,-no-whole-archive.
like image 110
servn Avatar answered Oct 13 '22 00:10

servn