问题
Context: In this answer, I learned that gcc's __builtin_unreachable()
can have some surprisingly impactful performance implications, as it seems that the following:
if(condition) __builtin_unreachable();
is being entirely stripped, and used as an optimization hint as long as condition
can be guaranteed to not have any side effect.
So my immediate reaction to this is that I should create the following macro, and use it absolutely everywhere I would normally use assert()
, since side-effect inducing code inside an assert()
would be a major bug in the first place:
// TODO: add handling of other compilers as appropriate.
#if defined(__GNUC__) && defined(NDEBUG)
#define my_assert(condition) \
if(!(condition)) __builtin_unreachable()
#else
#define my_assert(condition) assert(condition)
#endif
From a standards perspective, this would create a split in functionality between normal and NDEBUG
builds, which you could make an argument excludes this macro from being the standard behavior of assert()
. However, since my code would be functionally dead in the water in the case of assertion failures regardless, it's fully equivalent from a behavioral standpoint.
So my question is: Can anyone think of a reason not to do this (appart from asserts that involve a lot of indirections)?
Before you ask, yes, I've checked that gcc's behavior is to void cast the assertion away in NDEBUG
builds.
回答1:
Yes, there is a reason to not use it.
Some people use the following defensive code practice that combines assert and exception ( assert(x>0); if (!(x<0)) throw std::logic_error("..")
) - see this answer:
Test Cases AND assertion statements
Your macro silently breaks the exception-part for release builds.
来源:https://stackoverflow.com/questions/46150723/is-there-any-reason-not-to-wrap-assert-in-a-macro-that-resolves-to-builtin-u