静态初始化程序在库中时会被优化掉

时间:2015-09-15 11:04:12

标签: c++ gcc

我有一个静态调用初始化例程的函数。插件系统需要这是动态加载(可以正常工作)或者也可以静态链接的插件系统。 由于主应用程序不知道静态插件,它必须自己注册,以便主应用程序知道它(就像它是动态加载的插件一样)。

现在的问题是从未调用过初始化。但是,当我添加一个虚拟函数并从主应用程序调用它时,突然调用初始化程序。所以这对我来说就像是初始化是"优化"远离gcc。

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

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

文字&#34;注册......&#34;永远不会打印,但添加虚拟功能

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

...并从主应用程序调用它,然后打印所有已删除的文本。

那么我怎么能强迫静电初始化器不被扔掉呢?

我使用Mingw32和gcc 4.9.2(仅用于记录:))。

重要更新:相关代码位于静态库中。在这种情况下,它不会被触发,只有当模块直接链接到主应用程序时才会调用初始化程序。

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();

3 个答案:

答案 0 :(得分:2)

我无法重现错误,但volatile可以解决问题:

static volatile bool gCSVRegistered = registerPlugins();

答案 1 :(得分:2)

因此,对这个问题的评论最终使我走向了正确的方向。问题是该函数位于静态库中,如果代码未在主应用程序中使用,则不会调用该代码,因为链接器甚至不会将代码添加到可执行文件中。

有关详细说明,我发现了这个问题: Static initialization and destruction of a static library's globals not happening with g++

为了强制调用代码,我必须将注册移动到肯定需要的模块中(并因此被链接),或者使用链接器选项-Wl,--whole-archive

ld linker question: the --whole-archive option

答案 2 :(得分:1)

因为你不使用静态变量,所以它会被优化掉。为了防止您使用“used”属性告诉编译器需要它:

[[gnu::used]] const bool gCSVRegistered = registerPlugins();

(我还将static更改为const,因为可能您不希望在初始化后修改变量,并且默认情况下命名空间范围const对象为static

对于C ++ 03,您可以使用非标准GNU属性语法:

__attribute__((used)) const bool gCSVRegistered = registerPlugins();