在C++编程中,VERIFY(...)是一个好的实践吗?

10

另外,当出现问题时,它与抛出异常相比如何?


4
VERIFY()是什么?它不在C++标准库中...你是指断言语句(assert statement)吗? - Billy ONeal
看起来与MFC相关:http://msdn.microsoft.com/zh-cn/library/fcatwy09(VS.71).aspx - Amber
1
我想知道为什么标准库有assert()但没有verify()。 - Inverse
3个回答

23

VERIFY()ASSERT()(或标准库中的assert())的作用相同——让您捕获那些真的不应该发生的事情(即真正的代码漏洞,在发布之前需要修复的问题)。如果由于某种原因表达式为false,那么没有继续下去的必要,因为出现了非常严重的问题。

这反映在VERIFY()只在Debug模式下编译时停止程序并显示错误信息—在Release模式下,它是透明的。 VERIFY()ASSERT()的区别在于,VERIFY()在Release模式下仍会评估表达式,但它不关心结果——而ASSERT()在编译Release模式时完全从程序中删除,因此其中的表达式副作用将不会发生。

异常更适用于可能出错但可以从中恢复的情况,因为异常可以由程序的其他部分处理。


10
这个问题看起来很简单,但实际上涉及到一个巨大的主题:如何处理错误。
简单地说,assertverify是在开发过程中使用的工具,而异常和系统调用错误检查则是正常的生产代码的一部分,用于处理运行时错误
  • 断言(适用于assert和verify)是一种防御性编程风格中经常使用的工具。它们的主要目标是保护程序免受永远不应该发生的情况的影响,而且如果这种情况发生,程序员也不知道该怎么做。通常用于检查程序错误。在调试程序时,当不可能发生的事情发生时,通常希望尽快检测并报告它。这将简化错误更正。您可以将其与某些条件一起使用,甚至像assert(false)这样,通常用于检查switch的分支是否被捕获。
  • 我通常在处理我不确定行为的第三方代码时使用断言。对于正在开发中的自己代码的行为检查,我通常更喜欢使用单元测试。

    现在,正如Schroëdinger教给我们的那样,测量会改变事物。您可能有时会有调试模式下工作但启用assert时停止工作的代码。这通常是断言条件中隐藏错误的症状(副作用、时间敏感代码)。verify可以最大限度地减少这种风险,但它可能被认为是一种不良实践,就像在地毯下清除灰尘。

    对于您还没有设置真正错误处理的地方,也可以使用verify进行快速编码。我认为您不应该让任何verify进入生产代码中。

  • 异常是程序控制流的一部分。它们通常用于处理错误,但这不是它们唯一可能的用途(使用其他语言如Python的人将知道我在说什么)。它们也不应被视为唯一的错误管理工具。当未包装在c++知悉库中时,系统调用仍然返回错误代码而不是引发异常。

一般来说,异常应该由能够合理处理它们的最近对象捕获。

同时,并非所有异常都应该被视为致命错误并停止程序。想象一下,你正在处理一个通过异常返回错误情况的网络视频流库。如果库抛出一个“丢帧”的异常警告,你通常不希望停止程序,而只是为下一帧做好准备。

即使最好的做法是停止程序,你也不应该让异常自行处理(在生产代码中更不应使用assert达到这个目的)。应该始终存在一个顶级异常处理程序,用于这个目的,明确调用exit()之类的函数。如果没有这样做,仅表明程序员不关心可能发生的情况,很可能没有考虑过。


3
为“未捕获异常”添加顶级异常处理程序的缺点在于,当发生未捕获异常时,堆栈会被销毁到顶级处理程序;然后它将执行完全无趣的操作,例如指出发生了哪个异常,随后像你所说的那样,无论如何都退出程序。完全不处理它会给调试器提供一个机会,在std::terminate处停止程序,并且整个执行堆栈是可用和可检查的。 - rvalue

7
在Visual C++中,有两个宏用于检查条件:ASSERTVERIFY
在调试模式下,它们的行为相同:即它们都会评估它们的参数,如果结果为0,则使用断言失败对话框停止程序。
区别在于发布模式。在发布模式下,ASSERT完全从程序中删除:它根本不评估表达式。另一方面,VERIFY仍然评估表达式,只是忽略结果。
个人而言,我的观点是,如果在调试模式下检查很有价值,那么在发布模式下仍然很有价值,您可能不应该使用它们。只需进行测试并引发异常(或使用在调试模式下扩展为assert()并在发布模式下使用异常的自定义宏)。

1
一个有用的区别是,如果你有需要运行一段时间的“挑剔”测试,你可以将它们放在 ASSERT() 中,然后不必担心在发布模式下的性能损失。 - Amber
你对于在发布模式下进行调试模式检查的看法也得到了很好的支持! - Cameron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接