在Windows上捕获访问冲突

时间:2015-10-09 11:30:49

标签: c++ windows visual-studio exception access-violation

我正在尝试捕获应用程序中的所有未处理的异常,因此我可以在它们出现时保存日志文件。这是一个使用Visual Studio 2013编译的64位Windows应用程序,用C ++编写。为了测试,我使用VS生成的默认C ++ Win32项目。

我通过使用SetUnhandledExceptionFilter注册处理程序来捕获所有异常。这适用于/大多数/案例,但不是全部。捕获所有throw() - n异常,以及大多数硬件异常,例如浮点或访问冲突。不触发处理程序的代码是:

std::vector<int> foo(5, 0);
for (auto& f : foo)
    foo.erase(foo.begin() + 1);

相反,我只是得到标准的Windows崩溃对话框,而不会调用异常处理程序。但是,如果我在附带调试器的Visual Studio中运行它,它会正确报告访问冲突异常。其他类型的访问冲突也会触发处理程序:

float* ptr = nullptr;
float value = *ptr;

上面的代码会触发异常处理程序。

我尝试过使用try / catch或捕获SIGSEGV信号,但是第一个例子都没有触发。中止/终止信号也不会被调用。简而言之,当发生崩溃时,我不会得到通知。

我想知道是否有任何方法可以在我的应用程序中获得某种通知,然后由于第一个示例导致的访问冲突而崩溃?由于VS似乎能够检测到它,我假设有一种方法。

编辑: 我只想说明我在发布模式下运行代码,第一个示例中的错误不是由调试模式下的迭代器超出边界检查引起的。

EDIT2: 我包含了一个最简单的例子,我可以使用win32控制台应用程序。在这里看到: http://pastebin.com/8L1SN5PQ

确保在没有附加调试器的发布模式下运行它。

2 个答案:

答案 0 :(得分:3)

这些运行时错误的处理方式不同,它们不会产生SEH异常。大致归类于&#34;编程错误&#34;和#34;恶意软件攻击&#34;。如果您没有附加调试器,那么就像未被捕获的C ++异常一样提供信息,默认处理程序使用__fastfail()调用即时死亡。

您必须在main()函数中调用_set_invalid_parameter_handler()来改变它们的处理方式。您可以在自定义处理程序中抛出C ++异常,或者调用RaiseException()来触发catch-em-all处理程序或只是在那里报告它们。支持后者,您希望确保始终终止该过程。

请注意您的代码段不是最好的示例。在没有启用迭代器调试的情况下构建程序时,这是UB,例如使用默认设置的发布版本。 UB不保证您会收到SEH例外。如果确实如此,那么你必须非常仔细地编写你的异常过滤器,它将在仍然采用堆锁的情况下被调用,因此基本的东西无法工作。最好的方法是使用命名事件唤醒保护进程。然后采用minidump并终止程序。

答案 1 :(得分:0)

您没有看到异常,因为它是由C运行时在内部处理的。具体来说,它是一个边界检查,而不是访问冲突。

在调试器中运行它我发现它是vector中的第242行:

            _DEBUG_ERROR("vector iterators incompatible");

最终调用_CrtDebugReportWhttps://msdn.microsoft.com/en-us/library/8hyw4sy7.aspx

您可以使用_CrtDebugReportW来控制_CrtSetReportMode的行为。

请注意,这在发布模式下没有任何影响,因为它们是调试模式边界检查。