Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static initializer is optimized away when it is in a library

Tags:

c++

gcc

I have a function which calls an initialization routine statically. This is needed for a pluginsystem where the plugin is either dynamically loaded (which works fine) or can also be statically linked. Since the static plugin is not known to the main application it must register itself, so that the main app knows about it (just like it were a dynamically loaded plugin).

The problem now is that the initalization is never called. However, when I add a dummy function and call it from the main app, then the initializer is suddenly called. So this looks to me as if the initalization is "optimized" away from gcc.

static bool registerPlugins(void)
{
    std::cout << "Registering CSV static plugin ... " << std::endl;
    PluginManager::registerStaticPlugin(&PluginInfo);

    return true;
}
static bool gCSVRegistered = registerPlugins();

The text "Registering..." is never printed, but adding the dummy function

void helper(void)
{
    std::cout << "Registered: "  << gCSVRegistered << std::endl;
}

... and call it dfrom the main app, then all the exptected text is printed.

So how can I force the static initalizer to not get thrown away???

I'm using Mingw32 with gcc 4.9.2 (just for the record :)).

Important update: The relevant code is in a static library. In this case it doesn't get triggered, only when the module is linked directly to the main application the initalizer is called.

SSCCE

main.cpp:

#include <iostream>

const char *gData = NULL;

int main()
{
    if(gData)
        std::cout << "Registration: " << gData << std::endl;
    else
        std::cout << "Registration: NULL" << std::endl;

    return 0;
}

void registered(const char *pData)
{
    gData = pData;
}

static1.cpp

void registered(const char *pData);

static bool registration(void)
{
    registered("Static initializer 1");
    return true;
}

static bool reg = registration();

static2.cpp

void registered(const char *pData);

static bool registration(void)
{
    registered("Static initializer 2");
    return true;
}

static bool reg = registration();

static library: lib_main.cpp

void registered(const char *pData);

static bool registration(void)
{
    registered("Static initializer library");
    return true;
}

static bool reg = registration();
like image 858
Devolus Avatar asked Sep 15 '15 11:09

Devolus


Video Answer


2 Answers

So because of the comments on the question that finally led me into the right direction. The problem is that the function is in a static library and there the code is not called if it is not used in the main application, because the linker doesn't even add the code to the executable.

For a more detailed description I found this question: Static initialization and destruction of a static library's globals not happening with g++

In order to force the code being called, I have to either move the registration into a module that will be needed for sure (and thus gets linked in), or use the linker option -Wl,--whole-archive.

ld linker question: the --whole-archive option

like image 111
Devolus Avatar answered Sep 23 '22 20:09

Devolus


I can't reproduce the error, but volatile could do the trick:

static volatile bool gCSVRegistered = registerPlugins();
like image 32
alain Avatar answered Sep 23 '22 20:09

alain