eonil
eonil

Reputation: 85975

Writing debug build only assertion function ignoring side-effects

Today I discovered some of my assertion functions are still exist and being called in release build. Here's an example of my assertion function.

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();
    }
}

I think some side-effect in condition expression is preventing eliminating the assertion call.

For example,

assertWithReason(glGetError() == GL_NO_ERROR);

I expected this assertion call to be eliminated, but it is not. Because it is being executed before checking debug-build.

I am not sure how C++ handles this case, but as C++ is very strict language, it doesn't seem to be eliminated unless I put some special flag. Anyway, I intentionally wrote the assertions to be removed in release build.

Is it possible to write a function which is surely removed in release build in C++? Of course I can use preprocessor macro, but I want to avoid using preprocessor macro as much as possible.

I am using Clang, and compiler specific extension (such as GCC attribute) is also fine.

Upvotes: 0

Views: 181

Answers (2)

Mats Petersson
Mats Petersson

Reputation: 129364

I quite like using macros for this purpose. Yes, I know, Macros are evil, but just like knives (used wrong) are evil, they come in handy if you use them right.

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

Now you can also show where it failed (my_drawfunc.cpp: 34 : my_do_draw(): assertion failed: glGetError == GL_NO_ERROR or something like that.

Upvotes: 2

tohava
tohava

Reputation: 5412

In C++11 you can use lambda expressions. It is likely that constant propogation will make it so that is_debug is never evaulated, and even if it is, the lambda is not called.

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; });
}

Upvotes: 1

Related Questions