1

大家好!

我正在 Visual C++(托管代码)上开发 winForm 应用程序。此应用程序链接本机静态库,其中包含带有静态变量初始化的代码块:

cls.h

class Cls
{
public:
    static Cls* getInstance();

private:
    static Cls _instance;
protected:
    Cls(void);
};

cls.cpp

#include "StdAfx.h"
#include "Cls.h"

Cls::Cls(void)
{
}

Cls Cls::_instance;

Cls* Cls::getInstance()
{
    return &_instance;
}

我可以成功链接这些库,但是当我尝试使用getInstance()方法时,在调用我的应用程序的主函数之前出现运行时错误。

它是一个第三方库,所以我无法重建它或以任何其他方式重新定义Cls类。

App 项目使用/clr,入口点定义为main

我厌倦了寻找解决方案。我发现我必须更改入口点,但我不知道什么值是正确的。

请帮忙!

4

1 回答 1

4

您遇到了臭名昭著的“静态初始化命令惨败”。当静态对象在两个翻译单元中定义时,先初始化哪个是未指定的;因此,如果一个的构造函数引用另一个,您最终可能会在初始化之前访问它。唯一的保证是它们都将在main开始之前被初始化。

最好的解决方案是避免静态对象。特别是,您正在使用的 Singleton 反模式在 C++ 中很难正确使用,而且通常麻烦多于其价值。

如果你真的想这样做,那么你可以通过在函数中定义静态对象来解决这个问题:

Cls* Cls::getInstance()
{
    static Cls _instance;
    return &_instance;
}

这样做的缺点是它引入了“破坏顺序惨败”(从另一个静态对象的析构函数访问它可能不安全),并且在某些编译器中它可能不是线程安全的(尽管它应该在任何声称符合 C++11)。如果构造是线程安全的,那么每次访问都会有(小的)运行时成本,如果您有极端的性能问题,这可能是一个问题。

更新:我刚刚注意到你说这个邪恶的阶级是你无法控制的,无法改变。在这种情况下,您的选择是:

  • 摆脱这个库并使用一些不那么疯狂的东西,或者
  • 注意main在开始之前不要访问它的任何静态数据;特别是,请遵循我上面的建议并避免使用您自己的任何静态对象。
于 2012-07-10T14:37:57.900 回答