The boost documentation states:
The macro BOOST_VERIFY has the same behavior as BOOST_ASSERT, except that the expression that is passed to BOOST_VERIFY is always evaluated. This is useful when the asserted expression has desirable side effects[.]
However, that isn't necessarily true. This combination of preprocessor defines:
- BOOST_DISABLE_ASSERTS not defined
- BOOST_ENABLE_ASSERT_HANDLER defined
- BOOST_ENABLE_ASSERT_DEBUG_HANDLER defined
- NDEBUG defined
Causes BOOST_VERIFY(expr) to expand to BOOST_ASSERT(expr) because of BOOST_ENABLE_ASSERT_HANDLER. The BOOST_ASSERT(expr) then expands to ((void)0), because of BOOST_ENABLE_ASSERT_DEBUG_HANDLER and NDEBUG.
This causes knock-on effects, e.g. in the boost::mutex implementation for POSIX: The mutex is locked directly, but unlocked via BOOST_VERIFY(!boost::pthread_mutex_destroy(&m)), which is removed by the current BOOST_VERIFY logic. This causes deadlocks, which is how this issue was noticed.
Reading the documentation more carefully, it seems like BOOST_ENABLE_ASSERT_HANDLER and BOOST_ENABLE_ASSERT_DEBUG_HANDLER are intended to be mutually exclusive. Thus, I think either of these solutions is appropriate:
- Ensure that defining both
BOOST_ENABLE_ASSERT*HANDLER macros causes a hard #error.
- Adjust the ifdef that detects whether
BOOST_VERIFY should expand to BOOST_ASSERT or expand directly.
The boost documentation states:
However, that isn't necessarily true. This combination of preprocessor defines:
Causes
BOOST_VERIFY(expr)to expand toBOOST_ASSERT(expr)because ofBOOST_ENABLE_ASSERT_HANDLER. TheBOOST_ASSERT(expr)then expands to((void)0), because ofBOOST_ENABLE_ASSERT_DEBUG_HANDLERandNDEBUG.This causes knock-on effects, e.g. in the
boost::muteximplementation for POSIX: The mutex is locked directly, but unlocked viaBOOST_VERIFY(!boost::pthread_mutex_destroy(&m)), which is removed by the currentBOOST_VERIFYlogic. This causes deadlocks, which is how this issue was noticed.Reading the documentation more carefully, it seems like
BOOST_ENABLE_ASSERT_HANDLERandBOOST_ENABLE_ASSERT_DEBUG_HANDLERare intended to be mutually exclusive. Thus, I think either of these solutions is appropriate:BOOST_ENABLE_ASSERT*HANDLERmacros causes a hard#error.BOOST_VERIFYshould expand toBOOST_ASSERTor expand directly.