【问题标题】:Catch a Memory Access Violation in C++在 C++ 中捕获内存访问冲突
【发布时间】:2013-05-12 19:44:32
【问题描述】:

在 C++ 中,是否有标准方法(或任何其他方法)来捕获由内存访问冲突触发的异常?

例如,如果出现问题并且程序试图访问它不应该访问的东西,您将如何收到一条错误消息显示“内存访问冲突!”而不是仅仅终止进程而不向用户显示有关崩溃的任何信息?

我正在使用 MinGW 为 Windows 编写游戏,如果有帮助的话。

【问题讨论】:

  • 为什么有人要阻止试图修改受保护内存的狂暴程序终止?
  • 通常您不会“捕捉”这些问题,而是首先通过调试器(例如 GDB)运行它们来修复它们。
  • 我认为他只是想显示一个整洁的退出窗口而不是默认的操作系统窗口,然后让它终止。没有错。
  • 没有一般的方法可以从中恢复。由于您甚至不知道此时调用堆栈是否正常,因此实际上不可能抛出 C++ 异常(必须展开堆栈并销毁相关对象)。此外,你会在处理程序中写什么你确定是安全的?
  • 为了清楚起见:从 C++ 的角度来看,访问未分配的内存是未定义的行为,而不是例外。在操作系统级别可能有也可能没有例外,例如Windows 中的访问冲突或 Linux 中的分段错误。您也许可以按照 zakinster 的建议发出信号。

标签: c++ try-catch access-violation


【解决方案1】:

这对你帮助不大,但是如果你使用/EHa编译,在MSVC中可以使用try...catch(...)捕获访问冲突和其他SEH异常:

Live demo

#include <iostream>
int main() {
  try {
    *(int*)0 = 0;
  }
  catch (...) {
    std::cerr << "Exception!\n";
  }
}

输出:

Exception!

唯一的缺点是您无法知道出了什么问题。要了解有关该异常的更多信息,您可以使用 _set_se_translator 设置自定义 SEH 翻译函数,例如在 this article 中。

【讨论】:

  • 如何知道我的项目是否为 MSVC?
  • 如果您使用 Visual Studio 创建项目,那么它会使用 MSVC 进行编译。
【解决方案2】:

Access violation 是硬件异常,不能被标准try...catch 捕获。

由于硬件异常的处理是系统特定的,任何在代码中捕获它的解决方案也将是系统特定的。

在 Unix/Linux 上,您可以使用 SignalHandler 来捕获 SIGSEGV signal。

在 Windows 上,您可以使用 __try/__except statement 捕获这些 structured exception。

【讨论】:

  • 是否有可能有一个“主”进程启动实际应用程序,然后根据崩溃应用程序进程的返回码显示错误消息?
  • @rsethc 如果它们是两个不同的进程,这似乎是可行的。
  • 我认为还值得一提的是,有些系统没有 MMU(或 MPU),根本无法检测到内存访问冲突。
猜你喜欢
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 2016-01-07
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
相关资源
最近更新 更多