【问题标题】:what is "debug assertion failed"什么是“调试断言失败”
【发布时间】:2017-03-19 19:42:35
【问题描述】:

同样的源代码,编译成debug版本会抛出“debug assertion failed”。但是编译成release版本后,就可以正常执行了。

那么谁能详细解释一下“debug assertion failed”是什么意思?

我很确定源代码中存在问题。但是为什么编译成release版本可以正常执行呢?

【问题讨论】:

  • 这就是调试配置的重点。运行时库会告诉您失败的函数,这种失败往往难以诊断。这个额外的帮助在发布配置中被关闭。还有一些你绝对应该自己使用的东西,你的代码很少有太多的 assert() 调用。

标签: c++ visual-studio-2015


【解决方案1】:

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

了解这些 Visual Studio 功能如何与标准 C++ 功能 assertNDEBUG 交互非常重要,所以让我尝试解释一下:


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

NDEBUG 导致assert 宏不执行任何操作。 assert 是验证您的代码的某些假设的好方法。正如宏的名字所说,你用它来断言前置条件、后置条件和不变量;您认为您的代码正确执行的操作。

如果一个断言失败,那么你已经发现了一个错误。 您的代码没有按照您的想法执行。这是一个非常严重的问题,通常需要立即终止应用程序进程以防止进一步的问题。

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


我很确定源代码中有问题。但是为什么编译成release版本可以正常执行呢?

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

尽管出现错误,您的程序仍继续运行是一件坏事。它可能表现出未定义的行为,并且您没有注意到它在做奇怪的事情这一事实应该被认为是运气不好,因为对于未定义的行为,任何事情都可能随时发生。纯属巧合的正常运行只是隐藏了一个错误,该错误将在以后发生。


Visual Studio 中“调试构建”和“发布构建”配置背后的逻辑是,您在开发过程中发现所有错误,测试“调试构建”,而您的用户运行的“发布构建”没有更多错误检测,因为检测错误可能会减慢程序的速度。

就个人而言,我认为这种逻辑存在严重缺陷。考虑不要在任何地方默认定义NDEBUG,并且在那些性能实际受到影响的翻译单元中启用它。即使您知道程序不是您认为的那样,继续执行程序也可能很危险,因为应用程序逻辑变得未定义。 assert 专门设计用于为单个文件打开或关闭它。不幸的是,这个特性并没有被大量使用,这实际上关闭了许多程序中有价值的错误检测机制。


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

【讨论】:

  • 开头的段落有点误导。 NDEBUG 不是 Visual Studio 特定的;这是自 ISO C 90 以来的标准。Visual Studio 调试配置在更多方面有所不同,没错,但问题是关于 assert
  • @MSalters:你是对的。我已经进行了编辑来解释这一点。
  • 很好的编辑。编写 StackOverflow 答案的挑战在于广大受众;你有绝对的初学者和语言律师;)
  • @MSalters:确实!如果不出意外,回答关于 SO 的问题是一个很好的写作练习:)
猜你喜欢
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多