2012-02-29 164 views
0

我有一個靜態常量類成員,其調用靜態函數來初始化它的價值的情況:CoInitialize的()和靜態混亂

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

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

的問題是,A ::函數()具有本地靜態變量,需要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 :: Function()時初始化靜態成員變量A :: NUM時會調用ConInitialize(),並且這會在WinMain中的代碼執行之前發生,所以我想我可以將它從我的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; 
} 

現在程序運行正常,但它與訪問衝突,當我退出崩潰。誰能闡明爲什麼會發生這種情況?

編輯:我想,因爲靜態變量應該持續的程序的持續時間,當我調用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 = ... 

此代碼將在首次調用A :: Function之前初始化COM環境,並在執行結束時清理。

在最終使用某些com引用之前,您的問題極端可能是您銷燬了COM環境。這解釋了一旦從WinMain中刪除:: CoUnitialize,問題就會消失。

P.S.

雖然這是一個壞主意,但你可能不調用:: CoUninitialize在你的主線程,因爲操作系統將讓這個清理時,你的程序完成

P.S.S.

此外,我不得不承認,應該在CPP文件中定義_AppComScope,在該文件中將值賦給A :: NUM。否則,標準並不保證初始化的順序

+0

如果我創建了這種類型的類型的靜態變量(在其構造函數中初始化COM庫),並在同一複雜的其他靜態成員之前定義它單位,這意味着COM庫將爲所有遵循它的靜態成員做好準備,對嗎?當程序終止時靜態變量被破壞時,它們是否總是以相反的順序被銷燬,這樣com_object會最後被銷燬?如果是這樣,似乎這會工作,但我運氣不好,如果我有其他複雜單位中的其他靜態成員調用A :: Function()? – user987280 2012-02-29 22:53:13

+0

你是對的。對象將以相反的順序銷燬。如果您將這些聲明放在單獨的單元中,Standard未定義初始化\銷燬的順序。 – 2012-02-29 23:21:33

+0

@ user987280,當使用COM時,明確控制每個com引用的生命週期非常重要。因此,我建議您以避免過度使用靜態變量的方式重構代碼。 – 2012-02-29 23:29:43