Ahm*_*aid 80 c++ exception-handling
例
int *ptr;
*ptr = 1000;
Run Code Online (Sandbox Code Playgroud)
我可以使用标准C++捕获内存访问冲突异常,而无需使用任何特定的Microsoft.
小智 103
读它并哭泣!
我想到了.如果你不从处理程序中抛出,处理程序将继续,异常也将继续.
当你抛出自己的异常并处理它时,魔法就会发生.
#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");
}
Run Code Online (Sandbox Code Playgroud)
Vol*_*kyy 63
有一种非常简单的方法可以使用try - > catch(...)块在Visual Studio中捕获任何类型的异常(除以零,访问冲突等).一个小的项目设置调整就足够了.只需在项目设置中启用/ EHa选项.请参阅项目属性 - > C/C++ - >代码生成 - >将启用C++例外修改为"是和SEH例外".而已!
详情请见:http: //msdn.microsoft.com/en-us/library/1deeycx5(v = vs.)
unw*_*ind 38
不.当你做坏事时,C++不会抛出异常,这会导致性能损失.违反访问或零错误的事情更像是"机器"异常,而不是您可以捕获的语言级别的东西.
这种情况取决于实现,因此需要供应商特定机制才能进行陷阱.对于微软,这将涉及SEH,而*nix将涉及一个信号
一般来说,捕获访问冲突异常是一个非常糟糕的主意.几乎没有办法从AV异常中恢复,并且尝试这样做只会导致更难找到程序中的错误.
如上所述,在Windows平台上没有非Microsoft /编译器供应商的方法.但是,以正常的try {} catch(exception ex){}方式捕获这些类型的异常对于错误报告以及更好地退出应用程序显然很有用(正如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)
Run Code Online (Sandbox Code Playgroud)
最初的课程来自这篇非常有用的文章:
http://www.codeproject.com/KB/cpp/exception.aspx
至少对我来说,signal(SIGSEGV ...)另一个答案中提到的方法在使用Visual C++ 2015的Win32上不起作用.什么做的工作对我来说是使用_set_se_translator()中发现的eh.h.它的工作原理如下:
步骤1)确保在Project Properties/C++/Code Generation/Enable C++ Exceptions中启用SEH例外(/ EHa)是,如Volodymyr Frytskyy的回答中所述.
步骤2)调用_set_se_translator(),为新的异常转换器传入函数指针(或lambda).它被称为翻译器,因为它基本上只接受低级别异常并将其重新抛出,因为它更易于捕获,例如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());
});
Run Code Online (Sandbox Code Playgroud)
步骤3)像往常一样抓住异常:
try{
MakeAnException();
}
catch(std::exception ex){
HandleIt();
};
Run Code Online (Sandbox Code Playgroud)