Static initialization and destruction of a static library's globals not happening with g++
Asked Answered
I

1

25

Until some time ago, I thought a .a static library was just a collection of .o object files, just archiving them and not making them handled differently. But linking with a .o object and linking with a .a static library containing this .o object are apparently not the same. And I don't understand why...

Let's consider the following source code files:

// main.cpp
#include <iostream>
int main(int argc, char* argv[]) {
    std::cout << "main" << std::endl;
}

// object.hpp
#include <iostream>
struct Object
{
    Object() { std::cout << "Object constructor called" << std::endl; }
    ~Object() { std::cout << "Object destructor called" << std::endl; }
};

// object.cpp
#include "object.hpp"
static Object gObject;

Let's compile and link and run this code:

g++ -Wall object.cpp main.cpp -o main1
./main1
> Object constructor called
> main
> Object destructor called

The constructor an the destructor of the global gObject object is called.

Now let's create a static library from our code and use (link) it in another program:

g++ -Wall -c object.cpp main.cpp
ar rcs lib.a object.o
g++ -Wall -o main2 main.o lib.a
./main2
> main
  • gObject's constructor and destructor are not called... why?
  • How to have them automatically called?

Thanks.

Isomerize answered 26/11, 2009 at 16:23 Comment(0)
I
34

.a static libraries contain several .o but they are not linked in unless you reference them from the main app.
.o files standalone link always.

So .o files in the linker always go inside, referenced or not, but from .a files only referenced .o object files are linked.

As a note, static global objects are not required to be initialized till you actually reference anything in the compilation unit, most compilers will initialize all of them before main, but the only requirement is that they get initialized before any function of the compilation unit gets executed.

Impaste answered 26/11, 2009 at 16:25 Comment(4)
Thanks. It seems that linking with all .o files contained in a .a can be forced by using the linker option -Wl,--whole-archive (or -Wl,-all_load on MacOSX)...Isomerize
See also -force_load for MacOSXIsomerize
Will be there any problem, if both 1.o and 2.o from some.a have two global variables with the same name? Can they be linked into one executable (consider cases: the global is referred / not referred from executable)?Fluoro
It seems I found the answer to my question: these two symbols have to go into one symbol table for the executable, which creates a collision. When object files form separate libraries, the symbol tables are separated.Fluoro

© 2022 - 2024 — McMap. All rights reserved.