3

我是 windows api 的初学者,所以这里一定有一些我不明白的地方。在我的 main 函数中,我使用 try-catch 来捕获所有未捕获的异常,但由于某种原因,我从代码中其他地方抛出的异常永远不会被捕获。我的应用程序使用单个(主)线程。

我这样扔:

throw "ClassName::methodName() - Error message";

并在消息循环之外捕获异常:

try {
    while(GetMessage(args...)) {
        TranslateMessage(args...);
        DispatchMessage(args...);
    }
}
catch( const char * sExc ) {
    ::MessageBox(args...);
}

我首先认为这是类型不匹配的问题,但后来我添加了一个带有省略号的 catch(...) ,但我仍然什么也没发现。如果你问,是的,我确定抛出异常。这不是与某种异步或类似的问题有关吗?

谢谢你的帮助 !

4

2 回答 2

4

这取决于发送的特定消息。但是不,并非所有这些都允许通过 Windows 内部代码展开堆栈。特别是涉及窗口管理器的消息,例如 WM_CREATE。Windows 内部有一个支持程序,可以防止堆栈通过关键代码展开。在 64 位版本的 Windows 7 上运行的 32 位代码中的异常还有一个问题,当消息需要多次穿越 Wow64 边界时,它们可能会被吞没。在 Windows 8 中已修复。

在更高版本的 Windows 上,这也可以激活“自我修复”代码,自动激活一个 appcompat shim 来吞下异常。你会收到一个通知,很容易被解雇。然后,您将在 VS 输出窗口中看到第一次机会异常通知,但您的程序会继续运行。对用户来说可能是好的,但在你调试时不是很好。运行 Regedit.exe 并导航到 HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Persisted 并检查您的程序是否在此处列出。只需删除条目。

长话短说,在消息循环之外捕获异常是不安全的。您必须在窗口过程中执行此操作。

于 2013-09-13T18:01:12.110 回答
1

您正在谈论“Windows 结构化异常处理”(http://msdn.microsoft.com/en-us/library/windows/desktop/ms680657%28v=vs.85%29.aspx)。不会抛出 C++ 异常。

如果你想走麻烦的路线:_set_se_translator

另请参阅:C 程序可以处理 C++ 异常吗?(Windows API 不是 C++)

于 2013-09-13T13:38:18.603 回答