使用断言与退出,反之亦然有什么优势或含义?

时间:2020-09-11 14:47:55

标签: c++ c assert exit abort

据我了解,对assert(e)(其中e是一个布尔表达式)的调用执行的过程与if (!e) { printf("%s:%d: failed assertion `%s'\n", __FILE__, __LINE__, e); abort(); }类似,如果给定的表达式不正确,该操作会突然终止程序

另一方面,我可能不写assert,而是写像if (!e) { fprintf(stderr, "custom error message.\n"); exit(1); }这样的东西,天真地觉得这是一件更干净,更好的事情。

忽略assert可以使用NDEBUG标志全局关闭,您认为一个相对于另一个有什么优势?我是否有区分的权利,或者我不知道两者之间在概念上的区别,即让条件程序终止的两种方式都有自己的利基用例?如果是后者,请解释。谢谢。

3 个答案:

答案 0 :(得分:2)

您认为一个相对于另一个有什么优势?

使用宏是因为您希望能够通过条件编译将其删除。换句话说,您甚至不希望代码出现在二进制文件中。

我是否有区分的权利,或者我不知道两者之间在概念上的区别,是否让条件程序终止的两种方式都有自己的利基用例?

好吧,即使您将exit()用作“失败”退出代码,abort()1的行为也不相同。后者旨在立即终止程序而无需进一步的工作,并可能触发调试提示或保存进程空间的映像(尽管其确切功能取决于提供程序的供应商)。前者通过atexit()调用注册的功能。还有其他停止方式,请参见quick_exit()_Exit()

对于C ++,有更多关于行为差异的注意事项,例如是否运行了堆栈帧中变量的析构函数,是否运行了全局析构函数,如果在执行此操作时引发异常会发生什么情况,等等。

答案 1 :(得分:2)

assert的最大优点是它使人的意图清晰明了。如果您看到assert(some_condition),那么您就知道作者的意图是什么(即some_condition始终是true)。对于您的内联版本,只有当我实际阅读您的if块并意识到您将要显示错误消息并终止程序后,我才能确定意图。

较少的重要原因包括assert减少了复制/粘贴错误,some_condition自动变成了一个字符串(包括变量名的保留),并且工具可以理解它。

答案 2 :(得分:0)

'assert'是代码自动测试工具。有时,即使满足导致执行断言的条件,程序也不应停止在客户端(发行版)上的工作。 例如:

   switch(color)
   {
      case red:
        //...
      break;
      
      case green:
        //...
      break;
      
      default:
        assert(false && "unexpected color value. 'enum color' was modified?");
   }

另一个例子:

   if ( OkOrFailEnum::OK != result )
   {
      assert(false && "data access fail");
      throw std::runtime_error("Can not get index " + std::to_string(index));
   }    

同时,“ assert”是一种代码注释工具。

   inline unsigned Sum(unsigned* pPos, unsigned* pOffset)
   {
     assert(nullptr != pPos);                             // \
     assert(nullptr != pOffset);                          // | preconditions
     assert(*pPos + *pOffset < pOffset && "Overflow?");   // /
     
     return *pPos + *pOffset;
   }

断言:

 assert(*pPos + *pOffset < pOffset && "Overflow?");

意味着,Sum(..)函数不能正确使用大笔款项,并且在调用该函数之前必须进行一些检查。

相关问题