当前位置:  开发笔记 > 编程语言 > 正文

捕获访问冲突异常?

如何解决《捕获访问冲突异常?》经验,为你挑选了6个好方法。

int *ptr;
*ptr = 1000;

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



1> 小智..:

读它并哭泣!

我想到了.如果你不从处理程序中抛出,处理程序将继续,异常也将继续.

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

#include "stdafx.h"
#include 
#include 
#include 
#include 

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

}


这在gcc中不起作用,但在VC++中有效,但仅在"Debug"构建中有效.仍在为一个有趣的解决方案提供支持.将调用信号处理程序,但不会抛出异常.
@Fabio:当然__try/__除了会捕获AV
那行不通。当信号处理程序被调用时,堆栈帧和寄存器计数与普通函数堆栈帧不同(在某些系统上甚至可能不使用同一堆栈)。最好的办法是设置一个标志,以指示信号处理程序已被激活。然后在代码中测试该标志并抛出。
这极有可能引入未定义的行为。为了使它能够在POSIX上运行,必须没有安装任何其他信号堆栈(`sigaltstack`)(除非C ++异常展开实现允许),并且处理展开机制本身的每个运行时函数都应是信号安全的。

2> Volodymyr Fr..:

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

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



3> unwind..:

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


@Ahmed:是的,但是如果您使用它们,可能会发生“不可能”的事情。例如,某些在AV行代码之后的语句可能已经执行,或者在AV行之前的语句尚未执行。

4> JaredPar..:

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

一般来说,捕获访问冲突异常是一个非常糟糕的主意.几乎没有办法从AV异常中恢复,并且尝试这样做只会导致更难找到程序中的错误.


捕获访问冲突也不错 - 这对用户体验有好处.但是,在这种情况下,我唯一有意义的事情是 - 使用Bug Reporting GUI生成另一个进程并尝试创建当前进程转储.产生一个过程始终是成功的操作.然后,我做TerminateProcess()自杀.
捕获异常并默默忽略它是一个坏主意.在可能的情况下捕获异常并记录有关应用程序状态的信息以进行诊断是一个非常好的主意.我曾经为后端图形库编写了一个UI,需要一些调试.每次它崩溃,人们都来找我,因为他们知道我写了UI.我在后端周围放了一个信号陷阱,弹出警报,告诉用户图书馆崩溃了.人们开始去图书馆的作者.
绝对.AV代表了代码中的错误,捕获异常只会隐藏问题.

5> Damien..:

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


我看到使用Microsoft编译器被视为非法指令或访问冲突.有趣.

6> Michael..:

至少对我来说,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 
#include 

// 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();
};

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有