2011-03-13 62 views
6

根據MSDN Library中的GetMessage API,當出現錯誤時,它可能會返回-1。該文件提供常見錯誤的代碼段應被避免:將主消息循環中GetMessage()返回-1?

while (GetMessage(lpMsg, hWnd, 0, 0)) ... 

文獻說:

的返回-1的可能性值 意味着這樣的代碼可導致致命 應用錯誤。相反,使用代碼 這樣的:

BOOL bRet; 
while((bRet = GetMessage(&msg, hWnd, 0, 0)) != 0) 
{ 
    if (bRet == -1) 
    { 
     // handle the error and possibly exit 
    } 
    else 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

我的問題是,在每一個示例代碼,包括Visual Studio創建的默認應用程序,從微軟,主消息循環看起來如下:

while (GetMessage(&msg, NULL, 0, 0)) 
{ 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 

注意上面的GetMessage的第二個參數是NULL。如果上面的代碼是有效的,這是否意味着GetMessage在這裏不會返回-1,所以處理-1的返回值是不必要的?

回答

3

鑑於VS在默認情況下會給出錯誤的代碼,並且沒有人關心,所以很可能在當前版本的Windows中導致沒有問題

有可能某些未來版本的GetMessage返回-1。但是,由於錯誤的代碼現在必須在很多現有的應用程序中,所以這會破壞大量的現有代碼。鑑於微軟致力於向後兼容性,我認爲他們不太可能改變許多程序依賴的GetMessage的行爲。

儘管如此,你仍然應該遵循文檔。

+1

+1非常好說! – 2011-03-13 09:13:38

+0

我從來沒有遇到麻煩,沒有檢查返回-1,但是當我看到文檔時,我很困惑。 現在,我堅持什麼文件說。而當GetMessage返回-1時ASSERT()。 – sam 2011-03-15 05:33:37

+0

VS爲默認應用程序生成的代碼是正確的,因爲它不會傳遞任何過濾器並提供有效的'MSG *'參數。如果您閱讀['GetMessage'](http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms644936.aspx)的文檔,則會明確指定這兩種錯誤模式。再往下看它的位置*「避免這樣的代碼:」*它顯示了一個帶有'HWND'過濾器的例子。其他錯誤模式是可能的,但這些都是災難性的,無論如何不能合理處理。或者如何從損壞的消息隊列中恢復?在這一點上,它是遊戲結束,2P UP。 – IInspectable 2013-08-07 19:19:59

4

您應遵循GetMessage()的MSDN文檔中指定的規則。這樣做毫無痛苦,並且不像您的代碼中散佈大量消息循環。

Visual Studio團隊與Windows團隊是分開的,他們和其他人一樣犯了同樣的錯誤!

我的現實我無法想象GetMessage()返回一個錯誤,但這是錯誤處理的本質 - 這並不意味着你不應該正確處理錯誤。

+0

我剛剛發現有一系列來自MSDN的文章,名爲「Learn to Program for Windows in C++」。並且[BaseWindow示例](http://msdn.microsoft.com/en-us/library/ff485838(v = VS.85).aspx)在主消息循環中不檢查返回值-1。 – sam 2011-03-15 05:21:22

3

你所提到的文件說:

如果出現錯誤,返回值爲-1。例如,如果hWnd是無效窗口句柄或lpMsg是無效指針,則該功能失敗。

在你的第二個例子,這兩個案件涉及:msg是一個典型的堆棧分配結構,使&msg將永遠是一個有效的指針。 NULLhwnd參數中傳遞,並且是該參數的可接受值。 wMsgFilterMinwMsgFilterMax都是零,這也是一個有效的組合。

因此GetMessage()在參數驗證過程中不會失敗。在其他情況下(例如,內存已耗盡),文檔沒有明確提及它是否也返回-1。也就是說,我一直以與第二個例子相同的方式呼叫GetMessage()一段時間,而我從來沒有看到它返回-1並將我的消息循環變爲無限循環。當然,你的里程可能會有所不同,但這樣做似乎很安全。

+0

我正在處理的幾乎所有項目都不檢查返回-1,所以我認爲我相當安全。 – sam 2011-03-15 05:37:29

3

我的腸道(又名Raymond Chen通靈能力)告訴我,GetMessage(&msg, NULL, 0, 0)只會在極其罕見的災難性故障(如消息隊列的腐敗)中返回-1。在這種情況下,測試它有點像在C++程序中捕獲std :: bad_alloc:當它發生時,對它做任何事情可能都太遲了。讓流程掛起(通過忽略GetMessage()== -1)或死亡(通過不捕獲bad_alloc)是可以接受的,除非當然所述流程控制核電站。

這一切都取決於你想要如何正式。我會專門在商業應用程序中測試-1,但不會在爲個人使用而編寫的小實用程序中測試。

+3

如果核電站在Windows上運行,我們現在都會死掉。 – Thomas 2011-03-13 09:42:21