为什么我的UnhandledExceptionFilter没有被简单的除以零调用?

时间:2014-03-18 23:14:54

标签: c++ winapi exception visual-c++ unhandled-exception

我使用以下MSVC ++控制台应用程序代码(在Windows 8.1,Release,Win32上运行)尝试将顶级异常返回给我:

#include "stdafx.h"
#include <Windows.h>
#include <iostream>

using namespace std; 

LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS exception)
{
    printf("Got an unhandled exception.");
    return EXCEPTION_CONTINUE_SEARCH;
}

int _tmain(int argc, _TCHAR* argv[])
{
    SetUnhandledExceptionFilter(UnhandledExceptionFilter);
    int a = 0;
    int b = 0;
    int c = a / b;
    cin.get();
    return 0;
}

我的UnhandledExceptionFilter实际上似乎没有被调用此示例中抛出的除零异常,否则我会期望&#34;得到未处理的异常&#34;显示日志消息。那是为什么?

5 个答案:

答案 0 :(得分:7)

整数除零是未定义的行为。如果实现选择为此引发异常(或任何其他未定义的行为),那很好。如果某个实现选择来为某些未定义的行为引发异常,那也没关系。无论面对未定义的行为时实现的是什么都没关系。这不是他们的问题。

显然在Windows 8.1上运行MSVC ++,Win32不会在除以零时引发异常。

你永远不应该期望未定义的行为会产生预期的结果。

答案 1 :(得分:3)

如果应用程序在调试器下运行,则不会调用SetUnhandledExceptionFilter()指定的函数,这个想法是SetUnhandledExceptionFilter()只应该用于生成崩溃转储然后退出应用程序。如果您连接了调试器,这不是很有用,因此调试器将首先处理异常。

MSDN documentation引用了这个:

  

调用此函数后,如果进程中发生异常   没有被调试,异常使它成为未处理的   异常过滤器,该过滤器将调用异常过滤器函数   由lpTopLevelExceptionFilter参数指定。

答案 2 :(得分:0)

除以零实际上是一个CPU陷阱,不仅仅是编程意义上的异常。您应该定义陷阱处理程序而不是异常处理程序。

答案 3 :(得分:0)

在我看来,从操作系统的角度看,异常实际上并不是真正的未处理异常。您正在呼叫printf,因此您已在CRT中进行了关联。 IIRC,CRT处理从main转义的异常,但是从操作系统的角度来看,未处理的异常是逃避真正入口点的异常 - 即调用main的CRT函数。

我相信你真的想要一个矢量异常处理程序。

答案 4 :(得分:0)

1)如@zhenguoli所说,UnhandledExceptionFilter是在kernel32.lib中定义的,因此它不会链接。您需要将异常过滤器命名为其他名称。 UnhandledExceptionFilter就是由SetUnhandledExceptionFilter设置的异常处理程序。

2)@DavidHammen尚不清楚,因为在x86上确实使用异常向量0处理了div被零除,并且GetExceptionCode()将返回EXCEPTION_INT_DIVIDE_BY_ZERO。但是,正如@davidbak所说,在OP的示例中,编译器不允许这样做,因为未使用变量c并将其优化。如果使用c,则向量0处的异常处理程序将开始展开堆栈并最终调用UnhandledExceptionFilter作为过滤器表达式,该表达式包装在BaseProcessStartup中的线程入口函数周围,然后将调用您的处理程序(线程以BaseProcessStartup作为入口函数开始,并以实际线程入口函数作为参数)。 .exe进入功能将初始化CRT,然后调用main。请注意,divbyzero无法更早地捕获,因为看来c ++异常对象从未编译为EXCEPTION_INT_DIVIDE_BY_ZERO –请参见https://stackoverflow.com/a/6121690/7194773