【问题标题】:What are assertions? and why would you use them?什么是断言?你为什么要使用它们?
【发布时间】:2008-10-31 11:28:32
【问题描述】:

如何在 C++ 中完成断言?示例代码表示赞赏。

【问题讨论】:

    标签: c++ assert


    【解决方案1】:

    断言是一种明确检查代码所做假设的方法,它可以帮助您通过缩小可能出现的问题来追踪大量错误。它们通常只在您的应用程序的特殊“调试”版本中进行评估,因此它们不会减慢最终发布版本的速度。

    假设您编写了一个将指针作为参数的函数。您的代码很有可能会假定指针是非 NULL 的,那么为什么不使用断言显式检查呢?方法如下:

    #include <assert.h>
    
    void function(int* pointer_arg)
    {
        assert(pointer_arg != NULL);
    
        ...
    }
    

    需要注意的重要一点是,您断言的表达式绝不能有副作用,因为它们不会出现在发布版本中。所以永远不要做这样的事情:

    assert(a++ == 5);
    

    有些人还喜欢在他们的断言中添加一些小信息来帮助赋予他们意义。由于字符串总是评估为真,你可以这样写:

    assert((a == 5) && "a has the wrong value!!");
    

    【讨论】:

    • 我以前没见过带字符串的 anding。真的很有用!
    • 在 Perl 领域一直使用这种技巧(或类似的变体),即使用给出的示例:a == 5 || die("a 的值错误");为松散的布尔输入欢呼。
    • 这个字符串的另一个技巧是在发布代码中验证值,但在调试代码中断言。例如,首先使用 if(x>10) 检查,然后如果错误条件通过,则只需 assert(!"x out of bounds") 然后打印到日志文件等。
    • @David:通常断言语句会在失败时打印失败条件以及文件/行信息。因此,它为您提供的是人类可读的信息以及实际信息。等效地,您可以使用两个参数编写自己的断言:条件和消息。
    • David,您的 IDE 通常会在向您显示的错误消息中显示失败的表达式,因此如果您的表达式包含字符串,则会弹出
    【解决方案2】:

    断言是布尔表达式,通常应该始终为真。

    它们用于确保您所期望的也会发生。

    void some_function(int age)
    {
         assert(age > 0);
    }
    

    你编写了处理年龄的函数,你也“知道”你总是在传递合理的参数,然后你使用了一个断言。这就像说“我知道这永远不会出错,但如果真的出错了,我想知道”,因为,嗯,每个人都会犯错误。

    所以不要检查合理的用户输入,如果有可能出现问题的场景,不要使用断言。进行真正的检查并处理错误。

    断言通常仅用于调试构建,因此不要将具有副作用的代码放在断言中。

    【讨论】:

      【解决方案3】:

      断言用于验证设计假设,通常根据输入参数和返回结果。例如

      // Given customer and product details for a sale, generate an invoice
      
      Invoice ProcessOrder(Customer Cust,Product Prod)
      {
        assert(IsValid(Cust));
        assert(IsValid(Prod);
      '
      '
      '
        assert(IsValid(RetInvoice))
         return(RetInvoice);
      
      }
      

      运行代码不需要断言语句,但它们会检查输入和输出的有效性。如果输入无效,则调用函数中存在错误。如果输入有效而输出无效,则此代码存在错误。有关断言使用的更多详细信息,请参阅design by contract

      编辑:正如其他帖子中所指出的,assert 的默认实现不包含在发布运行时中。许多人(包括我自己)会使用的一种常见做法是将其替换为发布版本中包含的版本,但仅在诊断模式下调用。这可以通过完整的断言检查对发布版本进行适当的回归测试。我的版本如下;

      extern  void _my_assert(void *, void *, unsigned);
      
      #define myassert(exp)                               \
      {                                                   \
          if (InDiagnostics)                              \
              if ( !(exp) )                               \
                  _my_assert(#exp, __FILE__, __LINE__);   \
      }                                                   \
      

      此技术的运行时开销很小,但它可以更轻松地跟踪任何使其进入该领域的错误。

      【讨论】:

        【解决方案4】:

        使用断言检查“不可能发生”的情况。

        典型用法:检查函数顶部的无效/不可能参数。

        很少见,但仍然有用:循环不变量和后置条件。

        【讨论】:

          【解决方案5】:

          断言是允许您测试程序中可能存在的任何假设的语句。这对于记录程序逻辑(前置条件和后置条件)特别有用。失败的断言通常会引发运行时错误,并且表明您的程序存在严重问题 - 您的断言失败是因为您认为正确的事情不是。通常的原因是:你的函数逻辑有缺陷,或者你的函数的调用者给你传递了错误的数据。

          【讨论】:

            【解决方案6】:

            断言是您添加到程序中的东西,如果满足条件,它会导致程序立即停止,并显示错误消息。您通常将它们用于您认为在您的代码中永远不会发生的事情。

            【讨论】:

              【解决方案7】:

              这并没有解决从早期 C 时代就传给我们的 assert 功能,但是如果您的项目可以使用 Boost,您还应该注意 Boost StaticAssert 功能.

              标准 C/C++ 断言在运行时有效。 Boost StaticAssert 工具使您能够在编译时创建某些类的断言,甚至更早地捕获逻辑错误等。

              【讨论】:

                【解决方案8】:

                这是一个断言是什么的definitionhere 是一些示例代码。简而言之,断言是开发人员在任何给定点测试他(或她)关于代码状态的假设的一种方式。例如,如果您正在执行以下代码:

                mypointer->myfunct();
                

                您可能想要断言 mypointer 不为 NULL,因为这是您的假设—— mypointer 在调用之前永远不会为 NULL。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-11-08
                  • 2012-04-17
                  • 1970-01-01
                  • 2011-01-15
                  • 1970-01-01
                  • 2015-09-08
                  • 2017-09-08
                  • 1970-01-01
                  相关资源
                  最近更新 更多