Skip to content

BOOST_VERIFY can fail to evaluate its argument #47

@lucius-kruse

Description

@lucius-kruse

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions