93

My code is full of calls to assert(condition). In the debug version I use g++ -g which triggers my assertions. Unexpectedly, the same assertions are also triggered in my release version, the one compiled without -g option.

How can I completely disable my assertions at compile time? Should I explicitly define NDEBUG in any build I produce regardless of whether they are debug, release or anything else?

Mikel Rychliski
  • 3,455
  • 5
  • 22
  • 29
Abruzzo Forte e Gentile
  • 14,423
  • 28
  • 99
  • 173
  • 1
    Somewhat off topic: if you want debug information, `-g` is equivalent to `-g2`. `-g3` might be a better choice, since it makes available the most symbolic information. For example, at `-g3`, symbolic #defines will be available. I've seem some toolchains choke on `-g3`, though. Also, many external libraries also depend upon `-DDEBUG` for 'debug' builds (Posix only attests to `-DNDEBUG` for 'release' builds). – jww Sep 04 '12 at 17:32

5 Answers5

117

You must #define NDEBUG (or use the flag -DNDEBUG with g++) this will disable assert as long as it's defined before the inclusion of the assert header file.

nbro
  • 15,395
  • 32
  • 113
  • 196
GWW
  • 43,129
  • 11
  • 115
  • 108
42

Use #define NDEBUG

7.2 Diagnostics

1 The header defines the assert macro and refers to another macro,

NDEBUG

which is not defined by <assert.h>. If NDEBUG is defined as a macro name at the point in the source file where is included, the assert macro is defined simply as

#define assert(ignore) ((void)0)

The assert macro is redefined according to the current state of NDEBUG each time that <assert.h> is included.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 1
    Hi! If it is true that when I define -DNDEBUG, still a call to assert executes something i.e. ((void)0), is this going to spend minimum CPU cycles? I thought that was mapped simply to nothing i.e. completely NO CODE..isnt' this way? – Abruzzo Forte e Gentile Mar 18 '11 at 16:07
  • @Abruzzo: I also thought so until now, but giving it a second thought, this would leave an empty `;` instead, which may be problematic if the `assert` is inside an `if`, for instance. I am sure that the compiler optimizes lines like `0;` away – davka Mar 18 '11 at 16:17
  • @Abruzzo, and BTW, check whether your IDE or your build system allows you to specify a default template for a new project. Then you can have NDEBUG defined in the Release configuration of every new project – davka Mar 18 '11 at 16:20
  • 2
    @Abruzzo What do you mean by no code? There will be no code generated in the executable by ((void)0). And the standard requires that assert can be used anywhere an expression with void type can be used, so just replacing it with no tokens what so ever won't work. – James Kanze Mar 18 '11 at 16:39
  • 1
    The compiler optimizes it out at compile time. Think of it as a NOP. Useless NOPs get removed, but this is compiler dependent. For example, compiling MIPS code, one may have assembly files in which has NOPs which stay in there to cover the branch and load delays to where it is needed to align instructions to clock cyclic boundaries or else undefined behavior. – user2262111 Nov 02 '18 at 10:27
13

The -g flag doesn't affect the operation of assert, it just ensures that various debugging symbols are available.

Setting NDEBUG is the standard (as in official, ISO standard) way of disabling assertions.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
12

You can either disable assertions completely by

#define NDEBUG
#include <assert.h>

or you can set NDEBUG (via -DNDEBUG) in your makefile/build procedure depending on whether you want a productive or dev version.

dcn
  • 4,389
  • 2
  • 30
  • 39
6

Yes, define NDEBUG on the command line/build system with the preprocessor/compiler option -DNDEBUG.

This has nothing to do with the debugging info inserted by -g.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836