C++ / Windows - 无法捕获异常

3

我对Windows API是个初学者,所以这里一定有些东西我还不理解。在我的主函数中,我使用try-catch来捕获所有未处理的异常,但出于某种原因,我从代码其他地方抛出的异常却从未被捕获。我的应用程序只使用一个(主)线程。

我是这样抛出异常的:

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

在消息循环外捕获异常:

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

我最初认为这是类型不匹配的问题,但是当我添加了带有省略号的catch(...)时,仍然没有捕获到任何异常。如果你问,是的,我确定异常已经被抛出。这难道不是与某种异步相关的问题吗?
谢谢您的帮助!

字符串字面量被抛出到哪里了?它是在另一个线程上吗? - doctorlove
我尝试去掉const,但结果相同。虽然如此,如果是这样的话我会感到惊讶,因为在其他代码中我一直都这样做而没有关于const的问题,而且抛出的字符串是一个常量。 @Joachim Pileborg:不,我没有在其他地方捕获它。调试器出现以下错误消息:“Unhandled exception at 0x7c812fd3 in xxxxxxx.exe: Microsoft C++ exception: char at memory location 0x0012d124..” - Virus721
@doctorlove 正如我所说,这不是一个多线程应用程序,因此它来自同一线程。我假设DipatchEvent()正在调用我的窗口过程,这就是异常的来源。 - Virus721
你提到了调试器。在 Visual Studio 调试器中,默认设置是在异常被抛出时中断程序,即在它实际开始执行之前(即在堆栈展开和传播开始之前)。当程序中断时,尝试按下 F5 键 - 调试器可能会询问“将异常传递给正在调试的程序吗?”。 - Angew is no longer proud of SO
@Virus721,在代码中“throw”这一行上打一个断点。当断点被触发时,使用F11跳过该行。控制权应该转移到已捕获异常的位置。 - Ben
我尝试编译和运行发布版本,但仍然无法工作:我收到了一个关于运行时错误的错误消息,请联系您的应用程序支持等等,然后是通常的Windows XP错误报告弹出窗口。 - Virus721
2个回答

4
这取决于正在发送的具体消息。但并不是所有消息都允许通过Windows内部代码展开堆栈,特别是涉及窗口管理器的消息,例如WM_CREATE。 Windows中有一个后备措施,防止堆栈从关键代码展开。在运行在Windows 7的64位版本上的32位代码中,当消息需要多次穿越Wow64边界时,会出现异常问题。这个问题已经在Windows 8中得到解决。
在较新的Windows版本中,这也可以激活“自我修复”代码,自动激活一个appcompat shim来吞噬异常。您将收到通知,很容易忽略。然后,在VS输出窗口中看到第一次机会异常通知,但您的程序继续运行。对用户来说可能还好,但在调试期间不太好。运行Regedit.exe并导航到HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Persisted,检查您的程序是否在列表中。只需删除该条目即可。
简而言之,在消息循环之外捕获异常是不安全的。您必须在窗口过程中执行此操作。

谢谢你的回答。我已经将try-catch移动到窗口过程中了,但是我得到的结果仍然相同。抛出和捕获类型匹配,并且异常确实被抛出,所以我不知道哪里出了问题。 - Virus721
我没有什么可以看的了。我已经提到了注册表键。在调试+异常中,确保未选中抛出复选框。 - Hans Passant

1

但是为什么我可以在其他Windows程序中抛出普通异常呢? - Virus721

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接