2012-02-29 13 views
0

は、私はそれが価値だ初期化するために、静的な関数を呼び出す静的定数クラスのメンバーの状況があります。にcoinitialize()および静的混乱

//A.h 
class A 
{ 
public: 
static const int NUM; 
static int Function(); 
}; 

//A.cpp 
const int A::NUM = A::Function(); 

問題は::関数は()ローカル静的を持っているということですCOMライブラリを必要と変数は、CoInitializeを()を呼び出して初期化される:

//A.cpp 
int A::Function() 
{ 
static vartype m; 
if(SUCCEEDED(CoInitialize(NULL))) 
//Now m can be used and initialized. 
// m.CreateInstance.... 
} 

私は、以前私のWinMain関数でのCoInitialize()を呼び出した:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) 
{ 
if(SUCCEEDED(CoInitialize(NULL))) 
    { 
    MyApp* app = new MyApp; 

    app->Run(); 

    delete app; 

    CoUninitialize(); 
    } 

return 0; 
} 

しかし、静的メンバ変数A :: NUMがA :: Function()の呼び出しで初期化され、WinMainのコードが実行される前にConInitialize()が呼び出されたので、私のWinMain:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) 
{ 
//if(SUCCEEDED(CoInitialize(NULL))) 
    { 
    MyApp* app = new MyApp; 

    app->Run(); 

    CoUninitialize(); 
    } 

return 0; 
} 

は今、プログラムは正常に動作しますが、私は終了したときには、アクセス違反でクラッシュします。なぜ誰がこの現象が起こっているのかを明らかにすることはできますか?

EDIT:CoUninitialize()を呼び出すと、プログラムの実行中に静的変数が保持されるため、ローカル静的変数m(COMライブラリが必要)が問題になります。クラッシュは、このローカル変数mに関連しているようです。しかし、問題は、COMライブラリを必要とする静的変数に対して、いつCoUninitialize()を呼び出すことができますか? WinMainでifステートメントのコメントを外すと問題は解決しないようですが、CoInitialize()とCoUninitialize()を一度しか呼び出していないためです。

答えて

0

まず、このケースではRAIIを使用することができます。ただ、次のような単純なクラスを定義します。

class com_scope 
{ 
    com_scope(com_scope const&); 
    com_scope& operator= (com_scope const&); 
public: 
    com_scope() 
    { 
     ::CoInitialize(NULL); 
    } 
    com_scope(DWORD dwCo) 
    { 
     ::CoInitializeEx(NULL, dwCo); 
    } 
    virtual ~com_scope() throw() 
    { 
     ::CoUninitialize(); 
    } 
} 

は、次に静的定数のcom_scope _AppComScopeを定義します。声明

const int A::NUM = ... 

する前にこのコードは::関数の最初の呼び出しの前にCOM環境を初期化し、実行終了時にクリーンアップします。

いくつかのCOMリファレンスを使用する前に、COM環境を破壊するという問題が極端にある可能性があります。これは、WinMainから:: CoUnitializeを削除するとすぐに問題が消えるという事実を説明しています。

P.S.

それは悪い考えですが、あなたは呼び出すことはできません:: CoUninitializeのを、あなたのメインスレッドで、あなたのプログラムが

P.S.S.を完了したときOSは、このクリーンアップを行いますので、が、

また、A :: NUMに値を割り当てるCPPファイルで_AppComScopeを定義する必要があることを認めなければなりません。それ以外の場合、スタンドアートは初期化の順序を保証しません

+0

このタイプのクラス型のスタティック変数(そのコンストラクタでCOMライブラリを初期化する)を作成し、同じ複雑なつまり、COMライブラリは、それに続く静的メンバーのすべてに対して準備が整っていることを意味しますか?そして、プログラム終了時に静的変数が破壊されているとき、それらは常に逆の順序で破棄されるので、com_objectは最後に破棄されますか?もしそうなら、これはうまくいくようですが、A :: Function()を呼び出す他の複雑なユニットに他の静的メンバーがあると私は不運ですか? – user987280

+0

あなたは正しいです。オブジェクトは逆の順序で破棄されます。これらの宣言を別々のユニットに置いた場合、Standardは初期化の破棄の順序を定義していません。 –

+0

@ user987280、COMを使用する場合は、すべてのcom参照の有効期間を明示的に制御することが非常に重要です。したがって、静的変数の過度の使用を避ける方法でコードをリファクタリングすることをお勧めします。 –

関連する問題