program story

액세스 위반 예외 포착?

inputbox 2020. 10. 4. 11:02
반응형

액세스 위반 예외 포착?


int *ptr;
*ptr = 1000;

Microsoft 특정을 사용하지 않고 표준 C ++를 사용하여 메모리 액세스 위반 예외를 포착 할 수 있습니까?


아니. C ++는 성능 저하를 초래할 수있는 나쁜 일을 할 때 예외를 발생시키지 않습니다. 액세스 위반 또는 0으로 나누기 오류와 같은 것은 포착 할 수있는 언어 수준의 것보다 "기계"예외에 가깝습니다.


그것을 읽고 울십시오!

나는 그것을 알아. 핸들러에서 던지지 않으면 핸들러는 계속되고 예외도 계속됩니다.

마법은 당신이 자신의 예외를 던지고 그것을 처리 할 때 발생합니다.

#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");

}

try- > catch (...) 블록을 사용하여 Visual Studio 에서 모든 종류의 예외 (0으로 나누기, 액세스 위반 등)를 포착하는 매우 쉬운 방법이 있습니다. 사소한 프로젝트 설정 조정만으로도 충분합니다. 프로젝트 설정에서 / EHa 옵션을 활성화하기 만하면됩니다. 참조 프로젝트 속성 -> C / C ++ -> 코드 생성은 -> 수정은 "예 SEH 예외로"에 C ++ 예외를 활성화합니다 . 그게 다야!

자세한 내용은 http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx를 참조하십시오.


이러한 유형의 상황은 구현에 따라 다르므로 트랩을 위해 공급 업체별 메커니즘이 필요합니다. Microsoft와 함께 이것은 SEH를 포함하고 * nix는 신호를 포함합니다.

일반적으로 액세스 위반 예외를 포착하는 것은 매우 나쁜 생각입니다. AV 예외에서 복구하는 방법은 거의 없으며 그렇게하려고하면 프로그램에서 버그를 찾기가 더 어려워집니다.


언급했듯이 Windows 플랫폼에서이를 수행하는 비 Microsoft / 컴파일러 공급 업체 방법은 없습니다. 그러나 오류보고를위한 일반적인 try {} catch (예외 예) {} 방식으로 이러한 유형의 예외를 포착하고 앱을 더 우아하게 종료하는 것이 분명히 유용합니다 (JaredPar가 말했듯이 앱은 이제 문제가있을 수 있음). . 간단한 클래스 래퍼에서 _se_translator_function을 사용하여 try 핸들러에서 다음 예외를 포착 할 수 있습니다.

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)

원래 클래스는이 매우 유용한 기사에서 나왔습니다.

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


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:

#include <string>
#include <eh.h>

// 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();
};

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


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.

참고URL : https://stackoverflow.com/questions/457577/catching-access-violation-exceptions

반응형