【发布时间】:2019-08-16 12:12:07
【问题描述】:
在下面的代码中,我想根据Microsoft Page 关于异常处理模型的描述,使用c++ catch (...) 来捕获异步和同步异常。
我还将“异常处理模型”设置为 Yes with SEH Exceptions (/EHa) 值。
我分别测试了以下状态的代码:
-
当我在未分配的
char*(char *c;) 中复制一个字符串时,我可以在catch (...)部分捕获它的异常。 (但我知道这是一个未定义的行为!) -
但是当我在一个字符数组中复制一个字符串(字符串大于数组大小)时,我无法捕捉到任何异常!!
-
在第 2 种状态下,调试时出现 Access Violation 错误。但是为什么不能像第一个状态一样捕获它的异常呢??
-
我尝试了另一种解决方案,如:
但问题依然存在。
这是我的代码(我在未分配的 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