大家好!
我正在开发visual C ++(托管代码)上的winForm应用程序。 此应用程序链接本机静态库,其中包含带有静态变量初始化的代码块:
class Cls
{
public:
static Cls* getInstance();
private:
static Cls _instance;
protected:
Cls(void);
};
#include "StdAfx.h"
#include "Cls.h"
Cls::Cls(void)
{
}
Cls Cls::_instance;
Cls* Cls::getInstance()
{
return &_instance;
}
我可以成功链接这些库,但是当我尝试使用 getInstance()方法时,在调用我的应用程序的main函数之前会出现运行时错误。
这是第三方库,所以我无法重建它或以任何其他方式重新定义 Cls 类。
App项目使用 / clr ,入口点定义为 main 。
我厌倦了搜索解决方案。我发现我必须改变切入点,但我不知道什么值是正确的。
请帮忙!
答案 0 :(得分:4)
你遇到了臭名昭着的“静态初始化命令惨败”。当静态对象在两个翻译单元中定义时,它是未指定的,首先被初始化;所以,如果一个的构造函数引用另一个,那么在初始化之前你最终可能会访问它。唯一的保证是它们将在main
开始之前全部初始化。
最好的解决方案是避免使用静态对象。特别是,你正在使用的Singleton反模式在C ++中是相当棘手的,并且通常比它的价值更麻烦。
如果你真的想这样做,那么你可以通过在函数中定义静态对象来解决这个惨败:
Cls* Cls::getInstance()
{
static Cls _instance;
return &_instance;
}
这样做的缺点是它引入了“破坏命令惨败”(从另一个静态对象的析构函数访问可能不安全),并且它在某些编译器中可能不是线程安全的(尽管它应该是在任何声称符合C ++ 11的规定中)。如果构造是线程安全的,那么每次访问都会有(小)运行时成本,如果您遇到极端性能问题,这可能会成为一个问题。
更新:我刚刚注意到你说这个邪恶的阶级不在你的控制范围之内,无法改变。在这种情况下,您的选择是:
main
开始之前,请注意不要访问任何静态数据;特别是,请遵循我的建议,避免使用自己的静态物体。