2013-04-09 62 views
1

我實際上面臨着一個巨大的問題:我有一個單身人士班。我的程序是一個多線程的MFC,因此可以從不同的線程調用單例的構造函數。我用一個互斥體包圍了單例實例getter函數,以避免死鎖和多重構造。下面的意思函數的調用在第一次直接失敗。Singleton構造函數失敗C++ - 可能是什麼?

函數看起來象(LOG_MSG宏記錄給定的字符串到我的日誌文件):

MyClass& MyClass::singleton() 
{ 
    LOG_MSG("MyClass::singleton -> jump in"); 

    static CMutex oInitMutex; 
    try 
    { 
     CSingleLock oSingleLock((CSyncObject *) &oInitMutex, TRUE); 
     LOG_MSG("!!! SINGLETON LOCK OKAY !!!"); 
     static MyClass oMyClassInstance; 
     LOG_MSG("!!! SINGLETON CONSTRUCTION OKAY !!!"); 
     return oMyClassInstance; 
    } 
    catch(...) 
    { 
     CString excMsg("Unexpected exception by creating MyClass singleton instance!"); 
     LOG_MSG(excMsg); 
     throw excMsg; 
    } 
} 

我已經想通了,該單對象的建設不會失敗(因爲我們得到了「 !!! SINGLETON CONSTRUCTION OKAY !!!「消息)。

日誌輸出說道:

09.04.2013 ;07:14:51:832;"MyClass::singleton -> jump in" 
09.04.2013 ;07:14:51:841;"!!! SINGLETON LOCK OKAY !!!" 
... (constructor logs => NOTHING unexpected in it!!! everything runs fine, as they must!!!) 
09.04.2013 ;07:14:52:125;"!!! SINGLETON CONSTRUCTION OKAY !!!" 
09.04.2013 ;07:14:52:170;"Unexpected exception by creating MyClass singleton instance!" 

這是什麼意思?什麼時候返回語句拋出異常(s)?請幫我解決這個問題...

+1

它並不一定是導致異常的'return'說法,但'oSingleLock'的破壞目的?您必須在調試器中運行您的程序以獲取更多信息。 – 2013-04-09 06:39:36

+1

靜態對象需要互斥嗎?它不是一個指針,完整的對象是靜態的 – 2013-04-09 06:42:43

+0

那麼,爲什麼你的互斥體在try塊之外?爲這件事情得到了邪惡的計劃? – WhozCraig 2013-04-09 06:42:52

回答

1

SOLUTION:

I figured out the problem, it was not easy. To learn from my error, I will share the code, caused the failure.

In the constructor I use an sscanf function call in improper way:

const char* sBuffer; 
// some stuff here that fills the sBuffer up 
sscanf(sBuffer, "%X %X %X %X", &tags_[0], &tags_[1], &tags_[2], &tags_[3]); 

The array was defined in the singleton class as:

private: 
    char tags_[4]; 

Beware: the format codes awating specific type of variables to be able to write the data in. For example: in my case the tags_ array should be an array of integers instead of array of chars. Since the singleton class should store the tags_ , after indexing the 2nd, 3rd and 4th element, the sscanf function will write into an undefined place of memory, something will be overwritten about the static class's data, which caused multiple instancing of it, however: this can be avoided by mutexing, but in that case the mutex object will be overwritten. More infos about required types for (s)scanf can be found here and here .

結論:

Be smart and aware of using C-functions/low-level calls. Pay a lot of attention on input parameters, not only their value, but their type too. If you support other type as expected, the behaviour of your program will be undefined, but you won't get compiler error: it is very hard to find out that issue later on.

6

雖然這並沒有回答你的問題,但它仍然是一個解決方案,你的整體問題:你根本不需要互斥鎖的C++ 11標準[stmt.dcl]§4指定(談論static變量時本地函數):

If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.88 If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.

凡注88:

Note 88: The implementation must not introduce any deadlock around execution of the initializer.

換句話說,該編譯器爲您引入同步;不需要手動完成。

+0

我正在使用Visual Studio 6.0,那是必須的:所以,新的C++ 11標準將不必對我的代碼做任何事情...... :( – 2013-04-09 07:00:42

+2

@AV:在這種情況下, a)你會遇到很多問題;並且(b)當你需要幫助時,你最好提到你使用的是史前編譯器,因爲你使用的語言與現代C++有些相似。 – 2013-04-09 07:03:48

+0

@AV在這種情況下,我只給你一個建議:升級你的編譯器,或者如果這是一份工作,而你不允許升級,就退出。如果僱主強迫員工使用破損的工具,他們如果只允許使用木錘而不使用鋼錘,你會在施工中工作嗎? – Angew 2013-04-09 07:13:56

相關問題