10

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

4

3 回答 3

22
于 2010-04-15T02:50:35.860 回答
9

这个问题看起来很简单,但隐藏了一个巨大的主题:处理错误。

总而言之,我会说断言验证是在开发过程中使用的工具,而异常和系统调用错误检查是生产代码的正常部分,用于处理运行时错误

  • 断言(它适用于断言和验证)是主要用于防御性编程风格的工具。他们的主要目标是防止出现不应该发生的情况,而程序员不知道如果发生这种情况该怎么办。通常用于检查编程错误。当调试程序时发生不可能的事情时,您通常希望尽快检测并报告它。它将简化纠错。您可以在某些条件下使用它,甚至可以像assert(false)通常那样使用它来检查开关的分支是否从未被捕获。

    在处理行为我不确定的第三方代码时,我主要使用断言。为了检查我自己正在开发的代码的行为,我通常更喜欢单元测试。

    现在,正如薛定谔教导我们的那样,措施改变了一切。当启用断言并停止在发布模式下工作时,您有时可能会拥有在调试模式下工作的代码。它通常是断言条件中隐藏错误的症状(副作用,时间敏感代码)。验证尽量减少这种风险,但它可以被认为是一种不好的做法,比如在地毯后面扫灰尘。

    您还可以使用verify进行快速编码,作为尚未设置真正错误处理的地方的脚手架。我认为您不应该在生产代码中进行任何验证。

  • 异常是程序控制流的正常部分。大多数情况下,它们用于处理错误,但这并不是它们唯一可能的用途(那些使用其他语言如 python 的人会知道我在说什么)。它们也不应被视为唯一的错误管理工具。当未包装在可识别 c++ 的库中时,系统调用仍会返回错误代码,而不是引发异常。

    根据经验,异常应该被最近的能够合理处理它们的对象捕获。

    此外,并非所有异常都应视为致命错误并停止程序。想象一下,您正在处理一个通过异常返回错误案例的网络视频流库。如果库抛出一个帧被丢弃的异常警告,您通常不想停止程序,而只是让它为下一帧做好准备。

    即使最好的办法是停止程序,你也不应该让异常为你做这件事(你甚至没有理由在生产代码中为此目的使用断言)。为此目的,应该始终存在一个顶级异常处理程序,该处理程序显式调用 exit() 之类的。不这样做只是表明程序员不关心可能发生的事情,并且可能没有考虑过。

于 2010-04-15T04:02:53.227 回答
7

在 Visual C++ 中,有两个宏用于检查条件:ASSERTVERIFY.

在调试模式下,它们的行为相同:也就是说,它们都评估它们的参数,如果结果为 0,它们都会通过断言失败对话框停止程序。

区别在于发布模式。在发布中,模式ASSERT完全从程序中删除:它根本不评估它的表达式。VERIFY另一方面,仍然计算表达式,它只是忽略结果。

就我个人而言,我的观点是,如果检查在调试模式下很有价值,那么它在发布模式下也很有价值,你可能不应该使用它们中的任何一个。只需进行测试并引发异常(或使用扩展为assert()调试模式和发布模式异常的自定义宏)。

于 2010-04-15T02:52:04.760 回答