Skip to content

Intermediate Gotchas

The Assertion That Did Work

the counter that vanishes in a release build

int main() {
  int retries = 0;

  assert(++retries == 1);

  std::cout << "retries: " << retries << '\n';
}

Build it normally, then with -DNDEBUG. What does it print?

Answer

Normal build:

retries: 1

With -DNDEBUG:

retries: 0

The assertion's test is not merely disabled; it is never evaluated.

Why

assert is a macro for checking an invariant, not a place to do work. When NDEBUG is defined before <cassert>, its expansion does not evaluate the operand, so ++retries disappears completely. Both GCC 11.5 builds were quiet under -Wall -Wextra. Separate the effect that must happen from the condition that should be checked.

The fix

++retries;
assert(retries == 1);

Takeaway: never put a side effect inside assert; a release build may erase it.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry