什么是“调试断言失败”

Rub*_*ire 1 c++ visual-studio-2015

编译为调试版本的相同源代码将引发“调试断言失败”。但是当编译为发行版时,它可以正常执行。

那么谁能详细解释“调试断言失败”是什么意思呢?

我很确定源代码中有问题。但是,为什么将其编译为发行版后可以正常执行?

Chr*_*ckl 6

C ++没有“调试版本”和“发行版本”的概念。这只是Microsoft Visual Studio在IDE中用于两个不同默认配置的约定。它甚至不是Visual C ++,而是在IDE中。

了解这些Visual Studio功能如何与标准C ++功能assert和交互是很重要的NDEBUG,因此让我尝试解释一下:


Visual Studio“发布版本”配置的一个方面NDEBUG是,默认情况下为所有翻译单元定义了预处理器宏(在这种情况下,或多或少意味着“对于所有.cpp文件”)。相反,在“调试构建”配置中,NDEBUG默认情况下未为任何翻译单元定义。

NDEBUG使assert宏不执行任何操作。assert是验证有关代码的某些假设的好方法。就像宏的名称所说的那样,您可以使用它来声明前置条件,后置条件和不变式。您认为代码可以正确执行的操作。

如果断言失败,则说明您发现了一个错误。您的代码没有执行您认为的操作。这是一个非常严重的问题,通常需要立即终止申请过程以防止进一步的问题。

Visual Studio中“调试构建”配置的另一个方面是,它更改了断言失败时应用程序终止的方式,并通过向您显示“调试断言失败”消息框来报告错误。


我很确定源代码中有问题。但是,为什么将其编译为发行版后可以正常执行?

您可能没有assert在自己的代码中使用,而是在使用包含断言的某个库(也许是标准库?)中的代码。例如,一个断言可确保使用正确的参数调用函数。查看错误消息框确切说明的内容;它会给你一个提示。

即使有错误,您的程序仍然可以运行是一件坏事。它可能表现出不确定的行为,并且您没有注意到它在做奇怪的事情这一事实应该被认为是倒霉的,因为使用不确定的行为,任何时候都可能发生任何事情。完全出于巧合而正常运行只会隐藏一个错误,将来您会遇到这种错误。


Visual Studio中“调试版本”和“发行版本”配置背后的逻辑是,您在开发过程中发现了所有错误,并测试了“调试版本”,而用户运行的“发行版本”中没有更多的错误检测功能。 ,因为检测到错误可能会使程序变慢。

我个人认为这种逻辑存在严重缺陷。考虑NDEBUG默认情况下不定义任何地方,在实际影响性能的翻译单元中启用它。即使您知道程序不是您认为的那样,继续执行程序也是很危险的,因为应用程序逻辑变得不确定。assert是专门设计的,因此您可以为单个文件打开或关闭它。不幸的是,此功能使用不多,有效地关闭了许多程序中有价值的错误检测机制。


最后一句话:assert仅应用于检测错误。您不应使用它来处理与外部资源有关的错误(内存不足,网络错误,文件系统错误)或用户输入错误。