简体   繁体   中英

GCC __attribute__((constructor)) is called before object constructor

In my shared library I need to load some data into an unordered_map, and I try to do it in a function marked __ attribute__((constructor)). However I got the SIGFPE on every map operation. After some looking into stackoverflow I found that this means that unordered_map is uninitialized. This is quite unexpected and ununderstandable for me, because, at a glance, it violates C++ contracts. Anybody could help on how can I run this method after constructors were run? Here is a working example with my own constructor, which shows that it's not called:

#include <stdio.h>

class Ala {
    int i;
public:
    Ala() {
        printf("constructor called\n");
        i = 3;
    }

    int getI() {
        return i;
    }
};

Ala a;

__attribute__((constructor))
static void initialize_shared_library() {
    printf("initializing shared library\n");
    printf("a.i=%d\n", a.getI());
    printf("end of initialization of the shared library\n");
}

The outcome is

initializing shared library
a.i=0
end of initialization of the shared library
constructor called

however if one tries to use std::cout instead of printfs then it goes into SEGFAULTs immediately (because constructor of streams were not run)

__attribute__((constructor)) is a compiler extension, and so you left the realms of standard C++. It looks like GCC's constructor functions are run before global initialization.

The way to fix it is to use another vanilla C++ construct, for example a global object whose initialization is properly sequenced by defining it in the same TU as your other global:

Ala a;

static void initialize_shared_library() {
    printf("initializing shared library\n");
    printf("a.i=%d\n", a.getI());
    printf("end of initialization of the shared library\n");
}

static int const do_init = (initialize_shared_library(), 0);

If you use a function that returns the static local variable, the variable will be initialized the first time the function gets called. See: When do function-level static variables get allocated/initialized?

struct Ala {
   // Your code here
   static Ala& get_singleton();
};

Ala& Ala::get_singleton() {
   static Ala singleton;
   return singleton;
}

static void initialize_shared_library() {
    Ala& a = get_singleton();
    printf("initializing shared library\n");
    printf("a.i=%d\n", a.getI());
    printf("end of initialization of the shared library\n");
}

As others have said, it is usually better to encapsulate all the initialization process in a object and let the constructor do the work for you (the body of the constructor is executed after all the members of the class are initialized).

If you just want to run something after a is initialized there are several ways to do that without leaving Standard C++; here is one:

struct Ala2 : Ala
{
    Ala2()
    {
         // your init code here
    }
};

Ala2 a;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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