使用断言与退出(反之亦然)的优点或含义是什么?

问题描述 投票:0回答:3

据我了解,对

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
,您认为一个相对于另一个还有什么其他优势?我的区别是否正确,或者两者之间是否存在我不知道的概念差异,使得这两种条件程序终止方式都有自己的利基用例?如果是后者,请解释一下。谢谢你。

c++ c assert exit abort
3个回答
4
投票

assert
最大的优点就是意图明确。如果您看到
assert(some_condition)
,那么您就知道作者的意图是什么(即,
some_condition
始终是
true
)。使用您的内联版本,在我实际阅读您的
if
块并意识到您将显示错误消息并终止程序之前,我无法假设意图。

不太重要的原因包括

assert
减少了复制/粘贴错误,
some_condition
自动转换为字符串(包括保存变量名称),并且工具可以理解它。


3
投票

您认为其中一个相对于另一个还有什么其他优势?

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

我的区别是否正确,或者两者之间是否存在我不知道的概念差异,使得这两种条件程序终止方式都有自己的利基用例?

嗯,即使您使用

exit()
作为“不成功”退出代码,
abort()
1
的行为也不同。后者的目的是立即终止程序而不进行进一步的工作,并可能触发调试提示或保存进程空间的图像(尽管它的确切作用取决于提供它的供应商)。前者通过
atexit()
调用注册的函数。还有其他停止方法,请参阅
quick_exit()
_Exit()

对于 C++,对于行为差异有更多的考虑,例如堆栈帧中变量的析构函数是否运行,全局析构函数是否运行,如果执行此操作时抛出异常会发生什么,等等。


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(..) 函数在处理大和时无法正常工作,并且必须在调用该函数之前进行一些检查。

© www.soinside.com 2019 - 2024. All rights reserved.