C++ 为什么我的UnhandledExceptionFilter没有在一个简单的除零上被调用?

C++ 为什么我的UnhandledExceptionFilter没有在一个简单的除零上被调用?,c++,winapi,exception,visual-c++,unhandled-exception,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

我正在使用以下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;
}
#包括“stdafx.h”
#包括
#包括
使用名称空间std;
长WINAPI UnhandledExceptionFilter(PEException\u指针异常)
{
printf(“得到一个未处理的异常。”);
返回异常\u继续\u搜索;
}
int _tmain(int argc,_TCHAR*argv[]
{
SetUnhandledExceptionFilter(UnhandledExceptionFilter);
int a=0;
int b=0;
INTC=a/b;
cin.get();
返回0;
}

My
UnhandledExceptionFilter
实际上似乎从未在本例中抛出的除法为零的异常上被调用,否则我将期望显示“get an unhandled exception”日志消息。这是为什么?

整数除以零是未定义的行为。如果实现选择为此(或任何其他未定义的行为)引发异常,则可以。如果一个实现选择为一些未定义的行为引发异常,也可以。当遇到未定义的行为时,实现所做的任何事情都可以。这不是他们的问题

显然,在Windows8.1上运行的MSVC++中,Win32不会在除法为零时引发异常


永远不要期望未定义的行为会导致预期的结果。

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

参考资料如下:

调用此函数后,如果在 未被调试,并且异常使其成为未处理的 异常过滤器,该过滤器将调用异常过滤器函数 由lpTopLevelExceptionFilter参数指定


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

在我看来,从操作系统的角度来看,这些异常实际上并不是一个真正的未处理异常。您正在调用
printf
,因此已在CRT中链接。IIRC,CRT处理从
main
转义的异常,但从操作系统的角度来看,未处理的异常是转义真实入口点的异常,即调用main的CRT函数

我相信您实际上需要一个向量化的异常处理程序

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

  • @DavidHammen不清楚,因为在x86上,div by zero确实是用异常向量0处理的,
    GetExceptionCode()
    将返回
    exception\u INT\u除以\u zero
    。但是,正如@davidbak所说,在OP的示例中,编译器不允许这样做,因为变量c没有被使用,并且将被优化。如果使用了c,那么向量0处的异常处理程序将开始展开堆栈,并最终调用
    UnhandledExceptionFilter
    作为一个过滤器表达式,该表达式围绕
    RtlUserThreadStart
    中的线程条目函数进行包装,然后调用处理程序(线程以
    RtlUserThreadStart
    作为入口函数启动,以实际线程入口函数作为参数)。
    .exe
    入口函数将初始化CRT,然后调用
    main
    。使用SEH是正确的,因为divbyzero只响应
    throw


  • 是否有任何方法重写此行为以捕获此信息?编译器也有可能优化了代码的这一部分-我知道即使使用
    -O1
    (在MinGW上)它也会为我这样做@Alexandru-一般来说,不是。这是未定义的行为。解决未定义的行为问题的方法是从一开始就不要调用它们。正如我看到的,您正在使用Windows…Windows支持uu try/u,但/u除外,它可以捕获这些异常类型。强烈建议防止Div-0,而不是捕获它。强烈建议防止Div-0,而不是捕捉它。是的。将可能的最大有符号整数添加到自身,取负数的平方根,或计算asin(2)也是如此。不要这样做。请注意,如果您正在使用Windows调试工具包中的
    ntsd
    cdb
    、或
    windbg
    ,您可以使用
    sx*
    命令系列控制在调试器中如何处理异常。默认情况下,它将在调试器中中断。我有一个si类名与埋在
    windows.h
    头文件中的类名之间的相似名称冲突。我的解决方案是稍微重命名我的类,使其不再与
    windows.h
    类名冲突。从编译器消息中并不总是可以明显看出
    windows.h
    内容是先被使用的。下面的示例OVIDID不能成功构建,因为<代码> unHealdExcel过滤器> /COD>已经在<代码> Kelnel.LIB < /C>链接中被定义。访问违反也是如此,但是Windows C++结构化异常处理确实会捕获定义的异常,如您所见的除零之外。请看这里。(.)GCC实现类似。域\u错误类无效\u参数类长度\u错误类逻辑\u错误类超出\u范围类溢出\u错误类范围\u错误类运行时\u错误类下溢\u错误类