断言() - 有什么好处?

时间:2012-08-28 14:53:55

标签: c++ assert

我不明白assert()的目的。

我的讲师说断言的目的是发现错误。

例如:

double divide(int a , int b ) 
{
  assert (0 != b);
  return a/b;
}

以上断言是否合理?我认为答案是肯定的,因为如果我的计划 不应该使用0(数字零),但不知何故零确实进入b变量,然后代码出错了。

我说错了吗?

你能告诉我一些合理的断言()的例子吗?

问候

6 个答案:

答案 0 :(得分:16)

assert用于验证应该始终为true的内容 程序是正确的。在您的示例中,assert是否合理 取决于divide的规范:如果b != 0是先决条件, 那么assert通常是验证它的首选方式:如果 有人在没有满足前提条件的情况下调用函数,它是一个 编程错误,你应该极端终止程序 偏见,做尽可能少的额外工作。 (平时。 有些应用程序不是这种情况,而是它的位置 最好抛出异常,然后绊倒,希望最好。) 但是,如果divide的规范定义了b == 0时的somw行为(例如返回+/- Inf),那么您应该实现此而不是 使用断言。

此外,如果事实证明它可以关闭assert 需要太多的运行时间。但是,一般来说,这应该只在 代码的关键部分,并且只有在探查器显示您的情况下 真的需要它。

FWIW:与您的问题无关,但您发布的代码会有 返回0.0 divide( 1, 3 )。不知何故,我不认为这是 你想要什么。

答案 1 :(得分:7)

断言的另一个方面:
它们也是一种文档。

而不是像

这样的评论
// ptr is never NULL
// vec has now n elements

更好写

assert(ptr!=0);
assert(vec.size()==n);

评论可能会随着时间的推移而过时,并会引起混淆。 但断言一直在被证实 评论可以忽略。断言不能。

答案 2 :(得分:5)

你在assert的评估中非常注意,除了你在调试阶段通常使用assert的事实...这是因为你不想要一个assert在生产代码中触发...抛出异常(并正确处理它们)是生产级代码中运行时错误管理的正确方法。

通常,assert用于测试假设。如果在调试阶段代码中没有满足假设条件,特别是当您获得超出所需输入值的值时,您希望程序在遇到错误时挽救,这样您可以解决它。例如,假设您正在调用一个返回指针的函数,该函数应该从不返回NULL指针值。换句话说,返回NULL值不仅仅是错误条件的一些指示,但它意味着您对代码如何工作的假设是错误的。这是一个使用assert的好地方...你假设你的程序将以一种方式工作,如果没有,那么你不希望该错误传播导致一些疯狂的难以找到的错误否则......你想在它发生时把它弄好。

最后,您可以将内置宏与assert结合使用,例如__LINE____FILE__,它们会在代码中为您提供文件和行号以帮助您快速识别问题区域。

答案 3 :(得分:3)

断言的目的是在调试期间发出意外行为(因为它仅在调试版本中可用)。你的例子是断言的合理案例。下一行可能会崩溃,使用断言,您可以选择在命中行之前中断执行,并进行一些调试。

这通常与异常并行完成 - 你断言要发出错误的信号,并抛出异常来优雅地处理案件(甚至退出程序):

double divide(int a , int b ) 
{
  assert (0 != b);
  if ( b )
     return a/b;
  throw division_by_0_exception();
}

在某些情况下,您希望继续执行,但仍希望发出错误信号。

答案 4 :(得分:1)

Assert用于在调试环境中测试有关代码的假设。断言通常对最终构建没有影响。

它是否是有效的测试完全是另一回事。如果不熟悉您的申请,我们无法回答这个问题。

断言永远不会失败。如果您发现断言可能会失败,那么您需要使用if语句来处理条件不正确的情况。断言仅适用于您认为永远不会失败的条件。

答案 5 :(得分:1)

断言用于在代码执行期间检查不变量,这些是程序员假设始终保持不变的条件,如果它们与假设不同则代码中存在错误。

断言也可以用于检查前置条件和后置条件,第一个在一些代码块之前检查并验证提供的数据/状态是否正确,第二个检查某些计算的结果是否正确。这有助于缩小可能存在问题/错误的位置:

assert( /*preconditions*/ );
/*here some algorithm - and maybe more asserts checking invariants*/
assert( /*postconditions*/ );

一些合理断言的例子:

  1. 检查函数返回值,例如,如果调用某个外部API函数,并且只有在编程错误时才知道它返回一些错误值:
  2. WinAPI Thread32First函数要求提供的LPTHREADENTRY32结构已正确分配dwSize字段,如果出现错误则失败。断言应该抓住这个失败。

    1. 如果函数接受指向某些数据的指针,则在函数的开头添加assert以验证它是否为非null。如果此函数不能对空指针起作用,则这是有意义的。

    2. 如果锁定了具有设置超时的互斥锁,那么如果此超时结束,则可以使用assert来指示可能的竞争条件/死锁

    3. ......还有更多

      断言的好处是在里面添加一些信息,例如:

      断言(假和&&“这个断言的原因”);

      “此断言的原因”将在消息框中显示给您

      您可能还想知道我们还有静态断言,指示编译期间的错误。