【问题标题】:Cannot catch access violation exception by use of C++ catch(...) [duplicate]无法使用 C++ catch(...) 捕获访问冲突异常 [重复]
【发布时间】:2019-08-16 12:12:07
【问题描述】:

在下面的代码中,我想根据Microsoft Page 关于异常处理模型的描述,使用c++ catch (...) 来捕获异步和同步异常。

我还将“异常处理模型”设置为 Yes with SEH Exceptions (/EHa) 值。

我分别测试了以下状态的代码:

  • 当我在未分配的char* (char *c;) 中复制一个字符串时,我可以在catch (...) 部分捕获它的异常。 (但我知道这是一个未定义的行为!)

  • 但是当我在一个字符数组中复制一个字符串(字符串大于数组大小)时,我无法捕捉到任何异常!!

  • 在第 2 种状态下,调试时出现 Access Violation 错误。但是为什么不能像第一个状态一样捕获它的异常呢??

  • 我尝试了另一种解决方案,如:

    Catching access violation exceptions?

但问题依然存在。


这是我的代码(我在未分配的 char* 和字符数组上测试了 strcpy()):

int main()
{
    char c[3] = { 0 };        // Cannot catch any exception
    //char *c;                // Can catch exception

    try
    {
        strcpy(c, "abcdefghijklmnopqrstuvwxyz1234567890");
    }
    catch (...)
    {
        cout << "Undefined behavior!" << endl;
    }

    return 0;
}

【问题讨论】:

  • 它们都是未定义的行为,未定义的行为没有任何可以保证的行为。因此,您不能指望您的try/catch 捕获由 UB 引起的异常,因为可能没有任何异常。要走的路就是不要有任何未定义的行为。
  • 预先声明的事情发生异常。这里发生的是UB,那里不需要诊断。从“金属”的角度来看,只要写入允许进程写入的内存发生写入,超出数组边界就不会导致访问冲突。
  • @Swift-FridayPie 为什么当我将 strcpy 用于未分配的字符 * 时会出现异常?并且在第二种状态下我不能得到任何异常?
  • 第二种情况:你有一个未初始化的指针,它将被strcpy取消引用,即UB。实际上,指针的值是不确定的,一些随机值从未被 new 表达式或 malloc() 返回。使用该值作为地址写入会导致进程访问未分配给进程或不可写的内存。因此,它会导致分段错误或类似状态。
  • 对于程序而言,第一种情况比第二种情况危险得多,因为该程序不会继续运行。但并非总是如此:在大系统中,指针的随机值实际上可能是先前值之一,并且指向某个已使用的内存区域。在那里写入会导致数据或程序流的灾难性损坏。第一种情况可能会导致混淆的安全风险。例如。有两个缓冲区并且超过一个,您写入第二个缓冲区,结果,您可能会发送不打算发送的数据。最近ssh的心跳缺陷就是这种UB。

标签: c++ error-handling try-catch strcpy


【解决方案1】:

访问冲突不需要引发异常。

这里有未定义的行为。根据strcpy的文档

如果 dest 数组不够大,则行为未定义。如果字符串重叠,则行为未定义。

【讨论】:

  • 当然,但这不是真正的问题。他们说他们遇到了访问冲突,并且没有被抓住。最有可能强制内存保护错误的简单修改是strcpy(NULL, "die");
  • @paddy:访问冲突会导致异常吗?我不这么认为。如果是这样,它将被抓住。实现不需要为访问冲突引发异常。这就是这个答案所说的。
  • 不,它没有。答案只是使那些水域变得混乱,因为您顺便提及它,并用您对strcpy 文档的摘要来折叠它,而不是与strcpy 或未定义行为完全无关的单独事实。
  • @paddy 为什么当我将strcpy 用于未分配的char* 时会出现异常?并且在第二种状态下我不能得到任何异常?
  • @paddy。大多数实现都没有抓住这一点。在 POSIX 系统上,您可以通过使用信号的运行时处理程序来捕获一些信号,因为操作系统应该向进程发送某些信号,但在这种情况下,信号是不可接收的并导致进程关闭。在任何其他逻辑可能阻止它之前。这是一个明智的设计,否则错误的进程可能会损坏多用户环境,甚至导致操作系统无法运行(足以达到能够写入映射到内存的文件的状态)。
猜你喜欢
  • 2022-01-07
  • 2010-10-02
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 2012-11-14
  • 1970-01-01
  • 2015-08-28
相关资源
最近更新 更多