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クラスを再定義したりすることはできません。

アプリ プロジェクトは、 mainとして定義されたエントリ ポイント/clrを使用します。

解決策を探すのに疲れました。エントリ ポイントを変更する必要があることがわかりましたが、どの値が正しいかわかりません。

助けてください!

4

1 に答える 1

4

悪名高い「静的初期化順序の大失敗」に遭遇しています。静的オブジェクトが 2 つの翻訳単位で定義されている場合、どちらが最初に初期化されるかは指定されていません。したがって、一方のコンストラクターが他方を参照すると、初期化される前にコンストラクターにアクセスしてしまう可能性があります。唯一の保証は、main開始前にすべてが初期化されることです。

最善の解決策は、静的オブジェクトを避けることです。特に、あなたが使用しているシングルトンのアンチパターンは、C++ で正しく理解するのがかなり難しく、一般的には価値があるよりも面倒です。

本当にこれを行いたい場合は、関数内で静的オブジェクトを定義することで問題を回避できます。

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

これには、"destruction order fiasco" (別の静的オブジェクトのデストラクタからアクセスするのが安全ではない場合があります) が発生し、一部のコンパイラではスレッドセーフではない可能性があるという欠点があります (ただし、すべてのコンパイラではスレッドセーフである必要があります)。 C++11 準拠を主張している)。構築がスレッドセーフである場合、アクセスごとに (わずかな) ランタイム コストが発生します。これは、極端なパフォーマンスの問題がある場合に問題になる可能性があります。

更新: この邪悪なクラスは制御不能であり、変更できないとあなたが言っていることに気付きました。その場合、オプションは次のとおりです。

  • このライブラリを取り除き、それほど狂っていないものを使用するか、
  • 開始するまで静的データにアクセスしないように注意してくださいmain。特に、上記の私のアドバイスに従い、独自の静的オブジェクトは避けてください。
于 2012-07-10T14:37:57.900 に答える