4

I am using the following MSVC++ console application code (running on Windows 8.1, Release, Win32) to try and return a top-level exception back to me:

#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;
}

My UnhandledExceptionFilter doesn't actually seem to ever get called on the divide by zero exception that is being thrown in this example, otherwise I would expect the "Got an unhandled exception" log message to show up. Why is that?

Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • I have had a similar name collision between a class name and one buried within the `windows.h` header file. My solution has been to rename my class slightly to no longer collide with `windows.h` class names. It has not always been obvious from compiler messages that the `windows.h` content has been used first. – CPlusPlus OOA and D Mar 19 '14 at 01:23
  • 1
    The example you provided cannot be build successfully, because `UnhandledExceptionFilter` is already defined in `kernel32.lib` when linking. – zhenguoli Sep 12 '19 at 04:44

5 Answers5

8

Integer division by zero is undefined behavior. If an implementation choose to raise an exception for that (or for any other undefined behavior), that's fine. If an implementation chooses not to raise an exception for some undefined behavior, that's also fine. Whatever the implementation does when confronted with undefined behavior is fine. It's not their problem.

Apparently MSVC++ running on Windows 8.1, Win32 doesn't raise an exception on division by zero.

You should never expect undefined behavior to result in something expected.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • Is there any way to override this behavior in order to catch this? – Alexandru Mar 18 '14 at 23:23
  • 4
    There is also a chance that the compiler optimizes out this part of the code - I know it does it for me even with `-O1` (on MinGW) – Tomer Arazy Mar 18 '14 at 23:25
  • 1
    @Alexandru - In general, no. It's undefined behavior. The solution to undefined behavior problems is to never invoke them in the first place. – David Hammen Mar 18 '14 at 23:26
  • 4
    As I see you are using Windows... Windows supports __try/__except/__finally which can catch these exceptions types. Strongly recommend preventing Div-0 rather than catching it. – Chris Mar 18 '14 at 23:29
  • 3
    *Strongly recommend preventing Div-0 rather than catching it.* Yep. The same goes for adding the largest possible signed integer to itself, taking the square root of a negative number, or calculating asin(2). Just don't do it. – David Hammen Mar 18 '14 at 23:32
  • Interesting...what are all the different types of unhandled exceptions that the unhandled exception filter catches? Surely there must be a reference to these, right? I just wanna make sure I catch as much as possible in my code. :) – Alexandru Mar 19 '14 at 00:14
  • The reason why I ask this question is more for the purpose of this (interesting read if you guys are curious on how to produce a stack trace on an exception - but I'm still trying to tweak it to work the way I want it to): http://stackoverflow.com/questions/22487887/why-doesnt-stack-walking-work-properly-when-using-setunhandledexceptionfilter/22489045#22489045 – Alexandru Mar 19 '14 at 01:04
  • Answer is correct, but in this case it is @TomerArazy that has diagnosed the OP's problem correctly: in Release builds optimization is on and the variable `c` is unused. The compiler will omit it and the expression that initializes it - and the two lines above it as well - and the division will not be in the code. He could try writing `c` to the console: Then it won't be dead and the division will be evaluated. – davidbak Mar 21 '18 at 07:06
4

The function specified by SetUnhandledExceptionFilter() won't be called if the application is running under a debugger, the idea being that SetUnhandledExceptionFilter() should only be used to generate a crash dump and then exit an application. This isn't very useful if you have a debugger attached, so the debugger will handle the exception first.

The MSDN documentation references this:

After calling this function, if an exception occurs in a process that is not being debugged, and the exception makes it to the unhandled exception filter, that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.

masrtis
  • 1,282
  • 17
  • 32
  • 2
    Note that if you're using something like `ntsd`, `cdb`, or `windbg` from the Debugging Tools for Windows package you can control this with the `sx*` family of commands that control how exceptions will be handled in the debugger. By default it will break in the debugger. – Michael Burr Mar 19 '14 at 00:32
1
  1. as @zhenguoli says, UnhandledExceptionFilter is defined in kernel32.lib so it will not link. You need to name your exception filter something else. UnhandledExceptionFilter is what calls your exception Handler set by SetUnhandledExceptionFilter.

  2. @DavidHammen is unclear because div by zero is indeed handled with exception vector 0 on x86 and GetExceptionCode() would return EXCEPTION_INT_DIVIDE_BY_ZERO. But, as @davidbak says, in the OP's example compiler does not allow this as the variable c isn't used and will be optimised out. If c were used, then the exception handler at vector 0 would start unwinding the stack and eventually call UnhandledExceptionFilter as a filter expression which is wrapped around the thread entry function in RtlUserThreadStart, which will then call your handler (the thread is started with RtlUserThreadStart as the entry function with the real thread entry function as a parameter). The .exe entry function will initialise the CRT and then call main. You are right to use SEH because divbyzero can't be caught by C++ exception handling, which only responds to throw.

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42
0

Divide By Zero is actually a CPU trap, more than an exception as in programming sense. You should define a trap handler instead of an exception handler.

Cahit Gungor
  • 1,477
  • 23
  • 30
  • So is an Access Violation, but that is reliably caught by Windows Structured Exception Handling – MSalters Mar 19 '14 at 10:58
  • The exceptions that is defined, as you see divide-by-zero is not included. For details in Microsoft C++ Implementation look here.(http://msdn.microsoft.com/en-us/library/t65b74ad.aspx). GCC implementation is similar. domain_error Class invalid_argument Class length_error Class logic_error Class out_of_range Class overflow_error Class range_error Class runtime_error Class underflow_error Class – Cahit Gungor Mar 19 '14 at 11:32
  • Those are Standard C++ exceptions. I very intentionally wrote [Structured Exception Handling](http://msdn.microsoft.com/en-us/library/windows/desktop/ms679356(v=vs.85).aspx). As you see, division by zero is included. Twice even, for floating point and integer types. – MSalters Mar 19 '14 at 11:48
  • We're talking about Windows programming in this question and the OP is asking about a specific API: `SetUnhandledExceptionFilter`. Structured Exception Handling is the game. – davidbak Mar 21 '18 at 07:02
0

It looks to me like the exceptions isn't actually a true unhandled exception from the OS perspective. You're calling printf, so you have linked in the CRT. IIRC, the CRT handles exceptions escaping from main, but from the OS viewpoint an unhandled exception is one that escapes the true entry point - i.e. the CRT function which calls main.

I believe you actually want a Vectored Exception Handler.

MSalters
  • 173,980
  • 10
  • 155
  • 350