2011-03-13 56 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