액세스 위반 예외 포착? 않고 표준 C ++를 사용하여 메모리

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를 참조하십시오.


답변

적어도 나에게는 signal(SIGSEGV ...)다른 답변에서 언급 한 접근 방식 이 Visual C ++ 2015의 Win32에서 작동하지 않았습니다 . 무엇을 했던 나에 대한 작업은 사용하는 것이었다 _set_se_translator()에서 발견 eh.h. 다음과 같이 작동합니다.

1 단계 ) 활성화해야합니다 SEH 예외 (/ EHA)와 예 에서 C ++ 예외를 활성화 프로젝트 속성 / C ++ / 코드 생성 / 에 의해이 질문에 대해 언급 한 바와 같이, 볼로디미르 Frytskyy .

2 단계 )를 호출 _set_se_translator()하여 새 예외 변환기 에 대한 함수 포인터 (또는 람다)를 전달합니다 . 기본적으로 저수준 예외를 받아 다음과 같이 잡기 쉬운 것으로 다시 던지기 때문에 변환기라고합니다 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());
});

3 단계 ) 평소처럼 예외를 포착합니다.

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

답변

이러한 유형의 상황은 구현에 따라 다르기 때문에 트랩을 위해 공급 업체별 메커니즘이 필요합니다. 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


답변

예외 처리 메커니즘은 아니지만 C에서 제공하는 signal () 메커니즘을 사용할 수 있습니다.

> man signal

     11    SIGSEGV      create core image    segmentation violation

NULL 포인터에 쓰는 것은 아마도 SIGSEGV 신호를 유발할 것입니다.