Home » C++ » Catching access violation exceptions?

Catching access violation exceptions?

Posted by: admin November 29, 2017 Leave a comment

Questions:

Example

int *ptr;
*ptr = 1000;

can I catch memory access violation exception using standard C++ without using any microsoft specific.

Answers:

Nope. C++ does not throw an exception when you do something bad, that would incur a performance hit. Things like access violations or division by zero errors are more like “machine” exceptions, rather than language-level things that you can catch.

Questions:
Answers:

Read it and weep!

I figured it out. If you don’t throw from the handler, the handler will just continue and so will the exception.

The magic happens when you throw you own exception and handle that.

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <tchar.h>

void SignalHandler(int signal)
{
    printf("Signal %d",signal);
    throw "!Access Violation!";
}

int main()
{
    typedef void (*SignalHandlerPointer)(int);

    SignalHandlerPointer previousHandler;
    previousHandler = signal(SIGSEGV , SignalHandler);
    try{
        *(int *) 0 = 0;// Baaaaaaad thing that should never be caught. You should write good code in the first place.
    }
    catch(char *e)
    {
        printf("Exception Caught: %s\n",e);
    }
    printf("Now we continue, unhindered, like the abomination never happened. (I am an EVIL genius)\n");
    printf("But please kids, DONT TRY THIS AT HOME ;)\n");

}

Questions:
Answers:

There is a very easy way to catch any kind of exception (division by zero, access violation, etc.) in Visual Studio using try -> catch (…) block. A minor project settings tweaking is enough. Just enable /EHa option in the project settings. See Project Properties -> C/C++ -> Code Generation -> Modify the Enable C++ Exceptions to “Yes With SEH Exceptions”. That’s it!

See details here:
http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

Questions:
Answers:

This type of situation is implementation dependent and consequently it will require a vendor specific mechanism in order to trap. With Microsoft this will involve SEH, and *nix will involve a signal

In general though catching an Access Violation exception is a very bad idea. There is almost no way to recover from an AV exception and attempting to do so will just lead to harder to find bugs in your program.

Questions:
Answers:

As stated, there is no non Microsoft / compiler vendor way to do this on the windows platform. However, it is obviously useful to catch these types of exceptions in the normal try { } catch (exception ex) { } way for error reporting and more a graceful exit of your app (as JaredPar says, the app is now probably in trouble). We use _se_translator_function in a simple class wrapper that allows us to catch the following exceptions in a a try handler:

DECLARE_EXCEPTION_CLASS(datatype_misalignment)
DECLARE_EXCEPTION_CLASS(breakpoint)
DECLARE_EXCEPTION_CLASS(single_step)
DECLARE_EXCEPTION_CLASS(array_bounds_exceeded)
DECLARE_EXCEPTION_CLASS(flt_denormal_operand)
DECLARE_EXCEPTION_CLASS(flt_divide_by_zero)
DECLARE_EXCEPTION_CLASS(flt_inexact_result)
DECLARE_EXCEPTION_CLASS(flt_invalid_operation)
DECLARE_EXCEPTION_CLASS(flt_overflow)
DECLARE_EXCEPTION_CLASS(flt_stack_check)
DECLARE_EXCEPTION_CLASS(flt_underflow)
DECLARE_EXCEPTION_CLASS(int_divide_by_zero)
DECLARE_EXCEPTION_CLASS(int_overflow)
DECLARE_EXCEPTION_CLASS(priv_instruction)
DECLARE_EXCEPTION_CLASS(in_page_error)
DECLARE_EXCEPTION_CLASS(illegal_instruction)
DECLARE_EXCEPTION_CLASS(noncontinuable_exception)
DECLARE_EXCEPTION_CLASS(stack_overflow)
DECLARE_EXCEPTION_CLASS(invalid_disposition)
DECLARE_EXCEPTION_CLASS(guard_page)
DECLARE_EXCEPTION_CLASS(invalid_handle)
DECLARE_EXCEPTION_CLASS(microsoft_cpp)

The original class came from this very useful article:

http://www.codeproject.com/KB/cpp/exception.aspx

Questions:
Answers:

Not the exception handling mechanism,
But you can use the signal() mechanism that is provided by the C.

> man signal

     11    SIGSEGV      create core image    segmentation violation

Writing to a NULL pointer is probably going to cause a SIGSEGV signal

Questions:
Answers:

At least for me, the signal(SIGSEGV ...) approach mentioned in another answer did not work on Win32 with Visual C++ 2015. What did work for me was to use _set_se_translator() found in eh.h. It works like this:

Step 1) Make sure you enable Yes with SEH Exceptions (/EHa) in Project Properties / C++ / Code Generation / Enable C++ Exceptions, as mentioned in the answer by Volodymyr Frytskyy.

Step 2) Call _set_se_translator(), passing in a function pointer (or lambda) for the new exception translator. It is called a translator because it basically just takes the low-level exception and re-throws it as something easier to catch, such as std::exception:

// Be sure to enable "Yes with SEH Exceptions (/EHa)" in C++ / Code Generation;
_set_se_translator([](unsigned int u, EXCEPTION_POINTERS *pExp) {
    std::string error = "SE Exception: ";
    switch (u) {
    case 0xC0000005:
        error += "Access Violation";
        break;
    default:
        char result[11];
        sprintf_s(result, 11, "0x%08X", u);
        error += result;
    };
    throw std::exception(error.c_str());
});

Step 3) Catch the exception like you normally would:

try{
    MakeAnException();
}
catch(std::exception ex){
    HandleIt();
};

Questions:
Answers:

A violation like that means that there’s something seriously wrong with the code, and it’s unreliable. I can see that a program might want to try to save the user’s data in a way that one hopes won’t write over previous data, in the hope that the user’s data isn’t already corrupted, but there is by definition no standard method of dealing with undefined behavior.