我想意识到这种行为:
assert_robust(expression, commands)严格地像经典的assert(expression)那样工作。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 '\0');
/* Normal code */
}这很好,但是如何使宏assert_robust支持多个(任意)多个命令?(最好采用标准的C++方式)
和另一个问题是:
严格的调试和发布的仁慈是一件好事吗?
编辑:,我的想法是为什么要做这样的事情,因为如果程序中的一个bug有时比崩溃和用户丢失数据的时候更奇怪,那么它实际上要好得多。
发布于 2014-02-23 21:26:17
更有趣的问题是第二个问题:
严格的调试和发布的仁慈是一件好事吗?
我的经验是,在调试和发布构建中有不同的行为是一个可怕的想法。您正在注册生产中的问题,您将永远无法在调试构建中再现这些问题,因为这两者的行为是不同的。
除此之外,如果您首先在调试模式中断言,则断言应该用于标记编程问题,即无法安全恢复的情况。如果您可以在发布模式下安全地恢复,为什么要在调试中断言?如果你做不到,你是否愿意以一种你不太明白它会做什么的方式来摆弄生产数据?
发布于 2014-02-23 22:58:18
我不认为用这种方式使用断言是个好主意。通常,如果希望谓词始终为真,则使用断言,因为它是关键代码的一部分。如果这不是真的,显然有一个大问题和中止是合理的。但是越来越多的人使用assert作为调试的普通错误检查。在这种情况下,在发布模式下完全禁用它就足够了。它认为你应该决定这两种方法中的一种。
但是,如果您想在中止之前运行某种紧急命令,可以使用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);发布于 2014-02-23 23:04:23
在不考虑这是否是一个好主意的情况下,您可以使用宏将多个命令包装在一个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 */会被允许的,这会很奇怪。
https://stackoverflow.com/questions/21974645
复制相似问题