首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使稳健的断言?

如何使稳健的断言?
EN

Stack Overflow用户
提问于 2014-02-23 21:16:12
回答 3查看 94关注 0票数 1

我想意识到这种行为:

  • 当程序在调试模式下运行时,assert_robust(expression, commands)严格地像经典的assert(expression)那样工作。
  • 当程序在发布模式下运行时,如果表达式为false,则assert_robust(expression, commands)执行某些commands

这样做是可以的:

代码语言:javascript
复制
#ifdef NDEBUG
    #define assert_robust(expression, command) if (!(expression)) command;
#else
    #define assert_robust(expression, command) assert(expression); 
#endif

例如,这可以用来实现myfunction的容错:

代码语言:javascript
复制
char myfunction(const string& s, int i)
{
    assert_robust(i >= 0, return '\0');

    /* Normal code */
}

这很好,但是如何使宏assert_robust支持多个(任意)多个命令?(最好采用标准的C++方式)

和另一个问题是:

严格的调试和发布的仁慈是一件好事吗?

编辑:,我的想法是为什么要做这样的事情,因为如果程序中的一个bug有时比崩溃和用户丢失数据的时候更奇怪,那么它实际上要好得多。

EN

回答 3

Stack Overflow用户

发布于 2014-02-23 21:26:17

更有趣的问题是第二个问题:

严格的调试和发布的仁慈是一件好事吗?

我的经验是,在调试和发布构建中有不同的行为是一个可怕的想法。您正在注册生产中的问题,您将永远无法在调试构建中再现这些问题,因为这两者的行为是不同的。

除此之外,如果您首先在调试模式中断言,则断言应该用于标记编程问题,即无法安全恢复的情况。如果您可以在发布模式下安全地恢复,为什么要在调试中断言?如果你做不到,你是否愿意以一种你不太明白它会做什么的方式来摆弄生产数据?

票数 3
EN

Stack Overflow用户

发布于 2014-02-23 22:58:18

我不认为用这种方式使用断言是个好主意。通常,如果希望谓词始终为真,则使用断言,因为它是关键代码的一部分。如果这不是真的,显然有一个大问题和中止是合理的。但是越来越多的人使用assert作为调试的普通错误检查。在这种情况下,在发布模式下完全禁用它就足够了。它认为你应该决定这两种方法中的一种。

但是,如果您想在中止之前运行某种紧急命令,可以使用C++11中的新lambda函数:

代码语言:javascript
复制
void ASSERT(int expression, std::function<void()> func) {
    if(!expression) {
        if (func) func();
        abort();
    }
}

你可以这样用它:

代码语言:javascript
复制
ASSERT(a >= 0, []() { std::cerr << "ERROR" << std::endl;});

或者:

代码语言:javascript
复制
ASSERT(a >= 0, [this]() { this->terminate(); });

或者:

代码语言:javascript
复制
ASSERT(a >= 0, nullptr);
票数 0
EN

Stack Overflow用户

发布于 2014-02-23 23:04:23

在不考虑这是否是一个好主意的情况下,您可以使用宏将多个命令包装在一个do-while(0);循环中。

代码语言:javascript
复制
#ifdef NDEBUG
    #define assert_robust(expression, command) if (!(expression)) \
                                                 do{command;} while(0)
#else
    #define assert_robust(expression, command) assert(expression)
#endif

还请注意,我没有在宏的末尾包括分号。如果将它们包括在宏中,则类似于

代码语言:javascript
复制
assert_robust(cond1, command1) /* no semicolon here, no problem */
assert_robust(cond2, command2) /* no semicolon here, no problem */

会被允许的,这会很奇怪。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21974645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档