编写仅调试构建断言函数忽略副作用

时间:2013-07-25 11:26:02

标签: c++ conditional-compilation

今天我发现我的一些断言函数仍然存在并在发布版本中被调用。这是我的断言函数的一个例子。

bool const isDebugMode()
{
    return false;  // Will be controlled by preprocessor flag.
}
void assertWithReason(bool const condition, std::string const reason = "")
{
    if (isDebugMode() and not condition)
    {
        abort();
    }
}

我认为条件表达式中的一些副作用是阻止消除断言调用。

例如,

assertWithReason(glGetError() == GL_NO_ERROR);

我预计这个断言呼叫会被淘汰,但事实并非如此。因为它在检查debug-build之前正在执行。

我不确定C ++如何处理这种情况,但由于C ++是非常严格的语言,除非我放置一些特殊的标志,否则它似乎不会被删除。无论如何,我故意写了要在发布版本中删除的断言。

是否有可能在C ++的发布版本中编写一个肯定删除的函数? 当然我可以使用预处理器宏,但我想尽可能避免使用预处理器宏。

我正在使用Clang,编译器特定的扩展名(例如GCC属性)也没问题。

2 个答案:

答案 0 :(得分:2)

我非常喜欢将宏用于此目的。是的,我知道,Macros 邪恶,但就像刀(使用错误)是邪恶的,如果你正确使用它们就会派上用场。

 #define MY_ASSERT(x) do {\
       if (is_debug() && !x) assertFailed(__FILE__, __LINE__, __FUNCTION__, #x);\
     } while(0);

现在您还可以显示失败的位置(my_drawfunc.cpp: 34 : my_do_draw(): assertion failed: glGetError == GL_NO_ERROR或类似的内容。

答案 1 :(得分:1)

在C ++ 11中,您可以使用lambda表达式。持续传播可能会使得is_debug永远不会被评估,即使它是,也不会调用lambda。

class Debug { enum { is_debug = 1; } };

template <class F>
void assert(F f) { 
    if (is_debug && !f()) abort();
}

{
    int x = 6;
    assert([&]() { return x == 6; });
}
相关问题