C++ 捕获访问冲突异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/457577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Catching access violation exceptions?
提问by Ahmed Said
Example
例子
int *ptr;
*ptr = 1000;
can I catch memory access violation exception using standard C++ without using any microsoft specific.
我可以在不使用任何特定于微软的情况下使用标准 C++ 捕获内存访问冲突异常吗?
采纳答案by unwind
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.
不。当你做一些不好的事情时,C++ 不会抛出异常,这会导致性能下降。诸如访问冲突或除以零错误之类的事情更像是“机器”异常,而不是您可以捕获的语言级别的事情。
回答by
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");
}
回答by Volodymyr Frytskyy
There is a very easy way to catch any kind of exception (division by zero, access violation, etc.) in Visual Studiousing 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!
有一种非常简单的方法可以使用 try -> catch (...) 块在Visual Studio 中捕获任何类型的异常(除以零、访问冲突等)。一个小的项目设置调整就足够了。只需在项目设置中启用 /EHa 选项即可。请参阅项目属性 -> C/C++ -> 代码生成 -> 将 Enable C++ Exceptions 修改为“Yes With SEH Exceptions”。就是这样!
See details here: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
在此处查看详细信息:http: //msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
回答by Michael
At least for me, the signal(SIGSEGV ...)
approach mentioned in another answer did not work on Win32 with Visual C++ 2015. What didwork for me was to use _set_se_translator()
found in eh.h
. It works like this:
至少对我来说,signal(SIGSEGV ...)
另一个答案中提到的方法不适用于 Win32 with Visual C++ 2015。什么做的工作对我来说是使用_set_se_translator()
中发现的eh.h
。它是这样工作的:
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.
步骤 1) 确保在项目属性 / C++ / 代码生成 / 启用 C++ 异常中使用 SEH 异常 (/EHa)启用Yes,如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
:
步骤 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());
});
Step 3) Catch the exception like you normally would:
步骤 3) 像往常一样捕获异常:
try{
MakeAnException();
}
catch(std::exception ex){
HandleIt();
};
回答by JaredPar
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
这种类型的情况取决于实现,因此需要特定于供应商的机制才能捕获。对于微软,这将涉及 SEH,而 *nix 将涉及一个信号
In general though catching an Access Violation exception is a verybad 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.
一般来说,虽然捕获访问冲突异常是一个非常糟糕的主意。几乎没有办法从 AV 异常中恢复,尝试这样做只会导致更难找到程序中的错误。
回答by Damien
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:
如前所述,在 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)
The original class came from this very useful article:
原始类来自这篇非常有用的文章:
回答by Martin York
Not the exception handling mechanism, But you can use the signal() mechanism that is provided by the C.
不是异常处理机制,但是可以使用C提供的signal()机制。
> man signal
11 SIGSEGV create core image segmentation violation
Writing to a NULL pointer is probably going to cause a SIGSEGV signal
写入 NULL 指针可能会导致 SIGSEGV 信号
回答by David Thornley
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.
像这样的违规意味着代码存在严重错误,并且不可靠。我可以看到一个程序可能想要尝试以一种人们希望不会覆盖以前数据的方式保存用户数据,希望用户的数据没有被损坏,但根据定义没有标准方法处理未定义的行为。