예
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)
원래 수업은이 매우 유용한 기사에서 나왔습니다.
답변
예외 처리 메커니즘은 아니지만 C에서 제공하는 signal () 메커니즘을 사용할 수 있습니다.
> man signal
11 SIGSEGV create core image segmentation violation
NULL 포인터에 쓰는 것은 아마도 SIGSEGV 신호를 유발할 것입니다.