使用 assert 与 exit 或反之有哪些优点或含义?
What are the advantages or implications of using assert vs exit or vice versa?
据我所知,调用 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
标志全局关闭,您认为其中一个比另一个有什么其他优势?我的区别是否正确,或者两者之间是否存在我不知道的概念差异,这让条件程序终止的两种方式都有自己的利基用例?如果是后者,请说明。谢谢。
what other advantage do you think one has over the other?
使用宏是因为您希望能够通过条件编译将其删除。换句话说,您甚至不希望代码出现在二进制文件中。
Have I got the distinction right, or are there conceptual differences between the two which I am unaware of that let the two ways of conditional program termination have their own niche use cases?
嗯,即使您使用 1
作为“不成功”的退出代码,exit()
和 abort()
的行为也不相同。后者旨在立即终止程序而无需进一步工作,并可能触发调试提示或保存进程图像 space(尽管它的具体作用取决于提供它的供应商)。前者通过atexit()
调用注册函数。还有其他停止方法,请参阅 quick_exit()
和 _Exit()
。
对于 C++,有更多关于行为差异的考虑,例如堆栈帧中变量的析构函数是否为 运行,全局析构函数是否为 运行,如果在执行此操作时抛出异常会发生什么,等等
assert
最大的好处就是明目张胆。如果你看到 assert(some_condition)
那么你就知道作者的意图是什么(即 some_condition
总是 true
)。对于您的内联版本,在我真正阅读您的 if
块并意识到您将显示一条错误消息并终止程序之前,我无法假设意图。
不太重要的原因包括 assert
减少了 copy/paste 错误,some_condition
自动转换为字符串(包括保留变量名),并且工具可以理解它。
'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(..) 函数不能正确处理大数额,它必须在调用函数之前做一些检查。
据我所知,调用 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
标志全局关闭,您认为其中一个比另一个有什么其他优势?我的区别是否正确,或者两者之间是否存在我不知道的概念差异,这让条件程序终止的两种方式都有自己的利基用例?如果是后者,请说明。谢谢。
what other advantage do you think one has over the other?
使用宏是因为您希望能够通过条件编译将其删除。换句话说,您甚至不希望代码出现在二进制文件中。
Have I got the distinction right, or are there conceptual differences between the two which I am unaware of that let the two ways of conditional program termination have their own niche use cases?
嗯,即使您使用 1
作为“不成功”的退出代码,exit()
和 abort()
的行为也不相同。后者旨在立即终止程序而无需进一步工作,并可能触发调试提示或保存进程图像 space(尽管它的具体作用取决于提供它的供应商)。前者通过atexit()
调用注册函数。还有其他停止方法,请参阅 quick_exit()
和 _Exit()
。
对于 C++,有更多关于行为差异的考虑,例如堆栈帧中变量的析构函数是否为 运行,全局析构函数是否为 运行,如果在执行此操作时抛出异常会发生什么,等等
assert
最大的好处就是明目张胆。如果你看到 assert(some_condition)
那么你就知道作者的意图是什么(即 some_condition
总是 true
)。对于您的内联版本,在我真正阅读您的 if
块并意识到您将显示一条错误消息并终止程序之前,我无法假设意图。
不太重要的原因包括 assert
减少了 copy/paste 错误,some_condition
自动转换为字符串(包括保留变量名),并且工具可以理解它。
'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(..) 函数不能正确处理大数额,它必须在调用函数之前做一些检查。