是否可以有一个零成本assert(),这样代码就不必在调试和发布版本之间进行修改
Is it possible to have a zero-cost assert() such that code should not have to be modified between debug and release builds?
我注意到一些代码通常看起来像这样:
#ifdef DEBUG
assert(i == 1);
#endif //DEBUG
并且在您的原始代码中可能有几个这样的块。必须写出每一块是乏味和混乱的。
有这样一个函数可能吗:
auto debug_assert = [](auto expr) {
#ifdef DEBUG
assert(expr);
#endif //DEBUG
};
或者类似的东西:
#ifdef DEBUG
auto debug_assert = [](bool expr) {
assert(expr);
};
#else //DEBUG
void debug_assert(bool expr) {}
#endif //DEBUG
在未指定DEBUG标志的情况下获得零成本断言?(也就是说,它应该具有与在没有运行lambda等的情况下没有放入代码相同的效果,并由g++/clang编译器进行优化)。
正如@KerrekSB所提到的,您已经可以通过在包含<cassert>
之前定义NDEBUG
来禁用断言。确保在包含头文件之前对其进行定义的最佳方法是将其列为编译器的参数(对于gcc,它是-DNDEBUG
)
注意:assert
是通过将其替换为无运算表达式来删除的,在那里,参数根本不会求值(这与您建议的解决方案不同)!这就是为什么在assert
中不调用任何有副作用的函数是至关重要的。
为了完整起见:以下是assert
的实现方式:
#include <cstdio>
#include <cstdlib>
#ifndef NDEBUG
#define assert(EXPRESSION) ((EXPRESSION) ? (void)0 : (printf("assertion failed at line %d, file %s: %sn", __LINE__, __FILE__, #EXPRESSION), exit(-1)))
#else
#define assert(EXPRESSION) (void)0
#endif
介绍您自己的assert
风格的宏是非常常见的。你可能想这么做有很多原因:
- 您希望包含有关计算表达式的更多信息(请参阅Catch的
REQUIRE
,以及他们如何使用表达式模板将表达式分解为各个元素并字符串化) - 您想对程序执行除
exit()
之外的操作,例如抛出异常、向开发人员发送邮件、记录到文件、闯入调试器 - 即使在发布版本中也要计算表达式,这比根本不计算表达式更不容易出错(毕竟,如果它没有副作用,可以通过编译器优化来消除它,如果它有副作用,你就避免了heisenbug)
- 等等,等等(如果你有想法,你可以发表评论,我会把它添加到答案中)
相关文章:
- 当回溯以零开始时,如何调试崩溃
- 在linux上调试巨大的C++项目
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 正在VS调试器中监视映射条目
- 使用调试/崩溃报告将应用程序部署到客户端
- VC++本机单元测试,找不到调试符号
- 如何在C++生成器中禁用"使用调试.dcus"
- 使用vscode调试时,GDB意外退出
- 即使使用调试编译标志,表达式也是"optimized out"
- 调试 CUDA MMU 故障
- 小字符串优化(调试与发布模式)
- 调试和自由执行中的信号处理
- 调试编译的服务器在数据库打开时崩溃
- Visual Studio 调试优化如何工作?
- 如何配置Visual Studio Code以使用cygwin,cmake和gcc进行调试
- 从 exe 文件 (Visual Studio ) 启动时调试断言失败
- 如何在大型c++项目的可视化代码中设置调试
- Qt 调试显示行号
- 是否可以有一个零成本assert(),这样代码就不必在调试和发布版本之间进行修改