by Chris » Fri Jun 23, 2017 4:32 am
Graf Zahl wrote:To be honest, I think it's stupid to #define non-debugging state. It should have been the other way from the start.
From what I've heard, some system developers don't even like using NDEBUG. On Debian, for example, they explicitly remove NDEBUG from Release builds of packages specifically so asserts stay.
What bugs me most about the assert macro is that the preprocessor removes the code. If you want to disable the checks with NDEBUG, that's fine by me, but let the compiler see it and optimize it out. Like
Code: Select all
#ifndef NDEBUG
#define assert(x) do { if(!(x)) __assert_fail(#x); } while(0)
#else
#define assert(x) do { if(false && !(x)) __assert_fail(#x); } while(0)
#endif
Any sane compiler should optimize out the check in the latter case (C and C++ short-circuit conditionals; if the left side of && evaluates false, or the left side of || evaluates true, it will skip evaluating the right side since it can't affect the result, and consequently won't have any run-time side-effect). Not only would it handle issues like this, where references to classes or functions may or may not disappear in an assert, it would also handle cases where certain variables are only ever checked in an assert (assign values to a variable and check the value in an assert, but in Release builds the compiler complains that the variable is set but never used because the use was taken out before the compiler ever saw it).
</rant>
[quote="Graf Zahl"]To be honest, I think it's stupid to #define non-debugging state. It should have been the other way from the start.[/quote]
From what I've heard, some system developers don't even like using NDEBUG. On Debian, for example, they explicitly remove NDEBUG from Release builds of packages specifically so asserts stay.
What bugs me most about the assert macro is that the preprocessor removes the code. If you want to disable the checks with NDEBUG, that's fine by me, but let the compiler see it and optimize it out. Like
[code]#ifndef NDEBUG
#define assert(x) do { if(!(x)) __assert_fail(#x); } while(0)
#else
#define assert(x) do { if(false && !(x)) __assert_fail(#x); } while(0)
#endif[/code]
Any sane compiler should optimize out the check in the latter case (C and C++ short-circuit conditionals; if the left side of && evaluates false, or the left side of || evaluates true, it will skip evaluating the right side since it can't affect the result, and consequently won't have any run-time side-effect). Not only would it handle issues like this, where references to classes or functions may or may not disappear in an assert, it would also handle cases where certain variables are only ever checked in an assert (assign values to a variable and check the value in an assert, but in Release builds the compiler complains that the variable is set but never used because the use was taken out before the compiler ever saw it).
</rant>