首页 > 解决方案 > 在发布模式下使用 C++ 中的 VS2017 构建的应用程序不会因未处理的异常而中断

问题描述

这个问题指的是由 VS2017 构建但在 VS IDE 之外执行的本机 C++ 程序:

为什么在原生 C++ Release 版本中未处理的异常会被静默忽略,而 Debug 版本会捕获相同的异常并显示好的预期错误消息?

我尝试找到影响未处理的异常但失败的构建设置。

下面列出了生成异常的代码。
请注意,我不是在问如何修复此代码并避免异常(或如何处理它),而是如何在发布版本中取消忽略此异常,以便操作系统捕获并抱怨。

std::map<const string, const int> MyMap;

auto it = MyMap.find("Cant Find Me");
int res = it->second; //Dereferencing the end iterator causes the expected exception. This exception is not explicitly handled anywhere else.

为了回应一些关于调试断言与异常的评论,我尝试了以下引发异常的代码:

PCHAR p;
p = NULL;
*p = 'X';  //Provoke an exception by following a null pointer and awaiting the chaos and madness at its end...

在 MSVC IDE 外部执行时,此代码仍然不会引发任何错误消息。现在,Release 和 Debug 版本都会发生这种情况。

标签: c++exceptionx86visual-studio-2017

解决方案


取消引用结束迭代器是未定义的行为。允许实现做它想做的事。

在调试版本中,您的特定实现将其转换为带有人类可读消息的用户友好错误。这是一个调试帮助。

在发布版本中,它不会,因为发布版本不是用于调试的。保留调试代码会损害整体性能。

附录。您对第一个代码片段的情况分析如下。

  1. 取消引用结束迭代器通常会导致 CPU 异常。
  2. 发布版本主动使上述异常保持沉默。
  3. 调试版本会按照操作系统默认值处理异常,这会导致终止并显示一个很好的错误消息。

这种分析是不正确的。发生的情况如下:

  1. 取消引用结束迭代器是未定义的行为。允许实现做它想做的事。
  2. 在发布版本中,取消引用结束迭代器不会导致 CPU 异常或任何其他可立即捕获的错误,这对于std::stringx86 架构上的许多主流实现来说是正常的
  3. 在调试版本中,实现会主动导致程序在取消引用结束迭代器时引发用户友好的异常,以降低性能为代价。

至于第二个代码片段,它可能会或可能不会导致CPU异常,CPU异常可能会或可能不会导致用户友好的错误消息。它的行为是未定义的。目前尚不清楚为什么您决定(1)确实发生了异常,以及(2)它被实现默默地忽略了。绝对没有证据表明这一点。如果确实发生了 CPU 异常,则应用程序可能只是异常终止而没有任何用户可见的错误消息。包含调试器的 IDE 能够捕获异常终止并将其转换为用户友好的错误,即使对于发布版本也是如此。在 IDE 之外,您只能靠自己。


推荐阅读