捕获访问冲突异常?

时间:2009-01-19 13:27:03

标签: c++ exception-handling

实施例

int *ptr;
*ptr = 1000;

我可以使用标准C ++捕获内存访问冲突异常,而不使用任何特定于Microsoft的。

8 个答案:

答案 0 :(得分:102)

读它并哭泣!

我明白了。如果你不从处理程序中抛出,处理程序将继续,异常也将继续。

当你抛出自己的异常并处理它时,就会发生魔法。

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

}

答案 1 :(得分:62)

有一种非常简单的方法可以使用try - &gt;在 Visual Studio 中捕获任何类型的异常(除以零,访问冲突等)。捕获(...)块。一个小的项目设置调整就足够了。只需在项目设置中启用/ EHa选项。请参阅项目属性 - &gt; C / C ++ - &gt;代码生成 - &gt;将“启用C ++例外”修改为“是和SEH例外”。就是这样!

详情请见: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

答案 2 :(得分:36)

不。当你做坏事时,C ++不会抛出异常,这会导致性能损失。访问违规或除零错误之类的东西更像是“机器”异常,而不是您可以捕获的语言级别的东西。

答案 3 :(得分:8)

此类情况取决于实现,因此需要供应商特定机制才能进行陷阱。对于微软,这将涉及SEH,* nix将涉及信号

一般情况下,虽然捕获访问冲突异常是一个非常坏主意。几乎没有办法从AV异常中恢复,并且尝试这样做只会导致更难找到程序中的错误。

答案 4 :(得分:7)

如上所述,在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)

原始课程来自这篇非常有用的文章:

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

答案 5 :(得分:7)

至少对我来说,另一个答案中提到的signal(SIGSEGV ...)方法在使用Visual C ++ 2015的Win32上不起作用 为我工作的是使用_set_se_translator()中的eh.h。它的工作原理如下:

第1步)确保在项目属性/ C ++ /代码生成/启用C ++异常是,使用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());
});

第3步)像往常一样抓住异常:

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

答案 6 :(得分:3)

不是异常处理机制, 但是您可以使用C提供的signal()机制。

> man signal

     11    SIGSEGV      create core image    segmentation violation

写入NULL指针可能会导致SIGSEGV信号

答案 7 :(得分:-1)

这样的违规行为意味着代码存在严重问题,并且不可靠。我可以看到一个程序可能想要尝试以一种希望不会写入先前数据的方式保存用户的数据,希望用户的数据尚未被破坏,但根据定义,没有标准方法处理未定义的行为。