我有一个静态调用初始化例程的函数。插件系统需要这是动态加载(可以正常工作)或者也可以静态链接的插件系统。 由于主应用程序不知道静态插件,它必须自己注册,以便主应用程序知道它(就像它是动态加载的插件一样)。
现在的问题是从未调用过初始化。但是,当我添加一个虚拟函数并从主应用程序调用它时,突然调用初始化程序。所以这对我来说就像是初始化是"优化"远离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(仅用于记录:))。
重要更新:相关代码位于静态库中。在这种情况下,它不会被触发,只有当模块直接链接到主应用程序时才会调用初始化程序。
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();
答案 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
。
答案 2 :(得分:1)
因为你不使用静态变量,所以它会被优化掉。为了防止您使用“used”属性告诉编译器需要它:
[[gnu::used]] const bool gCSVRegistered = registerPlugins();
(我还将static
更改为const
,因为可能您不希望在初始化后修改变量,并且默认情况下命名空间范围const对象为static
对于C ++ 03,您可以使用非标准GNU属性语法:
__attribute__((used)) const bool gCSVRegistered = registerPlugins();