Search code examples
c++exceptionx86visual-studio-2017

Apps built with VS2017 in C++ in Release mode do not break on unhandled exception


This question refers to native C++ programs built by VS2017 but executed OUTSIDE of the VS IDE:

Why unhandled exceptions are silently ignored in native C++ Release builds, while Debug builds catch the same exception and display the nice expected error message ?

I tried finding the build setting, that affects the unhandled Exeptions but failed.

The code that generates the exception is listed below.
Note, that I am not asking how to fix this code and avoid the exception (or how to handle it), but how to unignore this exception in Release builds, so the OS catches it and complains.

std::map<const string, const int> MyMap;

auto it = MyMap.find("Cant Find Me");
int res = it->second; //Dereferencing the end iterator causes the expected exception. This exception is not explicitly handled anywhere else.

In response to some comments about Debug Assertion vs. Exception I have tried it with the following exception provoking code:

PCHAR p;
p = NULL;
*p = 'X';  //Provoke an exception by following a null pointer and awaiting the chaos and madness at its end...

This code still does not provoke any error messages when executed OUTSIDE of the MSVC IDE. This happens for BOTH the Release and Debug builds, now.


Solution

  • Dereferencing the end iterator is undefined behaviour. An implementation is permitted to do what it pleases.

    In debug builds, your particular implementation translates this to a nice user friendly error with a human readable message. This is a debugging aid.

    In release builds, it does not, because release builds are not meant for debugging. Leaving debugging code in would hurt overall performance.

    Addendum. It looks like your analysis of the situation with the first code fragment is as follows.

    1. Dereferencing an end iterator normally causes a CPU exception.
    2. The release build actively silences said exception.
    3. The debug build leaves the exception handled as per the OS default, which causes termination with a nice error message.

    This analysis is incorrect. What in happens is as follows:

    1. Dereferencing the end iterator is undefined behaviour. An implementation is permitted to do what it pleases.
    2. In the release build, dereferencing an end iterator does not cause a CPU exception or any other immediately catchable error, as is normal for many mainstream implementations of std::string on the x86 architecture
    3. In the debug build, the implementation actively causes the program to raise a user-friendly exception upon dereferencing an end iterator, for a price of reduced performance.

    As for the second code fragment, it may or may not cause a CPU exception, and a CPU exception may or may not cause a user-friendly error message. The behaviour of it is undefined. It isn't quite clear why you decided that (1) an exception does happen, and (2) it is being silently ignored by an implementation. There is absolutely no evidence that would suggest that. If a CPU exception does happen, the application probably just abnormally terminates without any user-visible error message. Your IDE, having included a debugger, is able to catch the abnormal termination and translate it to a user-friendly error, even for a release build. Outside of the IDE you are on your own.