如何做出稳健的断言
How to make robust assert?
我想实现这种行为:
- 当程序在调试模式下运行时,
assert_robust(expression, commands)
严格按照经典assert(expression)
工作 - 当程序在发布模式下运行时,如果表达式为 false,
assert_robust(expression, commands)
执行一些commands
这可以通过以下方式完成:
#ifdef NDEBUG
#define assert_robust(expression, command) if (!(expression)) command;
#else
#define assert_robust(expression, command) assert(expression);
#endif
例如,这可以用于使myfunction
容错
char myfunction(const string& s, int i)
{
assert_robust(i >= 0, return ' ');
/* Normal code */
}
这很好用,但是如何制作支持多个(任意)数量的命令的宏assert_robust
呢?(最好通过标准的C++方式)
另一个问题是:
调试严格,发布仁慈是好事吗?
编辑:我的想法为什么要做这样的事情是因为如果它是程序中的错误,程序维护有时比崩溃和用户丢失数据时有点奇怪,那么实用性要好得多。
更有趣的问题是第二个:
调试严格,发布仁慈是好事吗?
我的经验是,在调试和发布版本中具有不同的行为是一个可怕的想法。您正在注册生产中的问题,您将永远无法在调试版本中重现这些问题,因为两者的行为不同。
除此之外,如果您首先在调试模式下断言,您可能会声称这不会成为问题,断言应该用于标记编程问题,您无法安全恢复的情况。如果可以在发布模式下安全恢复,为什么要在 DEBUG 中断言?如果你不能,你是否愿意以一种你不太了解它能做什么的方式摆弄生产数据?
在不讨论这是否是一个好主意的情况下,您可以使用宏将多个命令包装在do-while(0);
循环中。
#ifdef NDEBUG
#define assert_robust(expression, command) if (!(expression))
do{command;} while(0)
#else
#define assert_robust(expression, command) assert(expression)
#endif
另请注意,我没有在宏的末尾包含分号。如果您将它们包含在宏中,则类似
assert_robust(cond1, command1) /* no semicolon here, no problem */
assert_robust(cond2, command2) /* no semicolon here, no problem */
会被允许,这真的很奇怪。
以这种方式使用断言不是一个好主意。通常,如果您希望谓词始终为真,则可以使用断言,因为它是关键代码的一部分。如果不是真的,那么显然存在一个大问题,中止是合理的。但是越来越多的人像普通的错误检查一样使用断言进行调试。在这种情况下,在发布模式下完全禁用它就足够了。它认为您应该决定采用这两种方法之一。
但是,如果您想在中止之前运行某种紧急命令,则可以使用 C++11 中的新 lambda 函数:
void ASSERT(int expression, std::function<void()> func) {
if(!expression) {
if (func) func();
abort();
}
}
你可以像这样使用它:
ASSERT(a >= 0, []() { std::cerr << "ERROR" << std::endl;});
或:
ASSERT(a >= 0, [this]() { this->terminate(); });
或:
ASSERT(a >= 0, nullptr);
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Python中的for循环与C++有何不同
- 尝试使用 std::vector<std::thread时出现静态断言失败错误>
- uint_not_usable_without_attribute在业力规则中使用数字生成器时静态断言失败
- C++ 使用增强正则表达式库时断言崩溃
- 在C++中释放内存期间,迭代器与指针有何不同
- 从 exe 文件 (Visual Studio ) 启动时调试断言失败
- 如何将向量断言到特征矩阵
- OpenCV - Python 断言错误:SAD 算法 - 立体相机视差图计算
- 使用 Google Test 对自定义断言函数进行单元测试
- 断言"id < 0"在Qt ActiveX中失败
- 初始值设定项列表构造和静态断言
- 在 CppUnit 中测试中止断言失败
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- 使用扫描的调试断言失败
- MS 本机单元测试 - 断言::线程失败不起作用
- 如何断言 CRTP 的函数为最终函数?
- 迭代器跳闸视觉C++ 2017 断言
- 如何在 google test in windows 中管理断言
- 如何做出稳健的断言