2

Where can I find an ASSERT similar to the assert(...) macro from the standard C++ library (the one defined in <cassert>), but that works on Release mode too? Or how should I write one?

I like assert(...) because it automatically prints the line my source file where the assertion failed, as well as the assertion expression. I expect those features (if possible) in the Release mode ASSERT as well.

a06e
  • 18,594
  • 33
  • 93
  • 169

5 Answers5

5

Basically assert is a macro that evaluates the expression and if it fails prints something and then aborts. It's not that hard to write something similar, something like.

#define ASSERT(x) do { if( !(x) ) { printfunc( #x ); abort(); } while(0)

Then you can modify that in order to suit your requirements. For example you might want not to abort in release mode. You could also adjust your printouts (to include just the information that you think is useful), in order to get file and line information you would use __FILE__ and __LINE__ macros (btw the #x in the define expands to a string literal containing the expression x).

skyking
  • 13,817
  • 1
  • 35
  • 57
2

In your release build, don't define NDEBUG, and assert will work.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • If I #undef NDEBUG, that won't mess with other compiler optimizations in Release mode? – a06e Aug 21 '15 at 14:41
  • 1
    See [what-is-the-ndebug-preprocessor-macro-used-for-on-different-platforms](http://stackoverflow.com/questions/5473556/what-is-the-ndebug-preprocessor-macro-used-for-on-different-platforms). In short `NDEBUG` is only used to disable `assert`. – Jarod42 Aug 21 '15 at 14:46
0

You can undefine NDEBUG

#undef NDEBUG

near the assert statement

or you can define your own assert

#define assert(x) printf(...)
Astinog
  • 1,151
  • 3
  • 12
  • 35
0

I've rolled out my own assertions that always fire in release mode too, based on this article:

This is the GIST of it, with me not providing the actual implementation (of AbstractAsserter, which is based on the article), but you get the idea:

#include <iostream>

struct AbstractAsserter
{
    virtual void doAssert(const char* expr, const char* file, int line, const char* function) const
    {
        std::cout << "Asserting now at " << expr << ", " << file << ", " << line << ", " << function << std::endl;
    }
};

struct Local
{
  const char* function_;
  const char* expr_;
  const char* file_;
  int line_;
  Local( const char* f, const char* ex, const char* file, int line )
  : function_( f ), expr_( ex ), file_( file ), line_( line )
  { }
  Local operator << ( const AbstractAsserter& impl )
  {
    impl.doAssert( expr_, file_, line_, function_ );
    return *this;
  }
};

// More to be added as required...
#if defined( __GNUC__ )
# define WE_FUNCTION __PRETTY_FUNCTION__
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
# define WE_FUNCTION __func__
#else
# define WE_FUNCTION "null_func()"
#endif


#define WE_ASSERT( expr )\
  if( expr );\
  else Local( WE_FUNCTION, #expr, __FILE__, __LINE__ )\
    << AbstractAsserter();


int main() {
    WE_ASSERT(!"bad BAD BOY!");
    return 0;
}

With this structure, your implementation may also do some critical saving of state etc (if you deem your program state trustworthy...debatable).

Werner Erasmus
  • 3,988
  • 17
  • 31
0

Using the std assert in release mode (where, by the comments, you would like compiler optimizations enabled), isn't a problem per se, as is established by the other answers. Writing a custom one has been done, so there's not much problem there.

However, to quote the Dr. Dobb's article:

Do use assertions liberally throughout your code; they are watchful, reliable guards that protect you (your program) from insanity

If you are worried to have assertion + compiler optimizations, then these two thing are a bit add odds conceptually:

  • Asserts should and can be used liberally, with the intention of finding bugs early, and mostly so that it doesn't matter whether the assert code hurts performance.
  • If you want/need to run with optimizations, you may not like the performance hit the additional (now optimized, but still) assert code gives you.

So, in summary, I see the use of a relase mode assert, but make sure to keep it separate from the "normal" assert, where most people would assume it to be off in release mode.

Community
  • 1
  • 1
Martin Ba
  • 37,187
  • 33
  • 183
  • 337