Modify

Opened 5 years ago

Last modified 4 years ago

#7028 reopened Feature Requests

NDEBUG should disable asserts even if BOOST_ENABLE_ASSERT_HANDLER is defined

Reported by: Mathias Gaunard Owned by: Peter Dimov
Milestone: To Be Determined Component: utility
Version: Boost Development Trunk Severity: Problem
Keywords: BOOST_ASSERT assert BOOST_ENABLE_ASSERT_HANDLER NDEBUG Cc: k_satoda@…

Description

I have some components that require the use of a specific assert handler.

Compiling those components in debug or release is something that should be fairly independent from the flags required to use my components.

Therefore it would be more practical for me if when both BOOST_ENABLE_ASSERT_HANDLER and NDEBUG are defined the assert handler is not called.

Attachments (1)

7028.patch (626 bytes) - added by viboes 5 years ago.
Is this patch enough?

Download all attachments as: .zip

Change History (23)

comment:1 Changed 5 years ago by Mathias Gaunard

Defining BOOST_DISABLE_ASSERTS instead of NDEBUG works. It would be good if both worked the same.

It also appears that BOOST_ASSERT has the problem but not BOOST_ASSERT_MSG.

comment:2 Changed 5 years ago by Kazutoshi Satoda <k_satoda@…>

Cc: k_satoda@… added

+1 for "when both BOOST_ENABLE_ASSERT_HANDLER and NDEBUG are defined the assert handler is not called".

Otherwise, a build configuration with BOOST_ENABLE_ASSERT_HANDLER needs additional control for BOOST_DISABLE_ASSERTS (unset for debug and set for release), which seems unreasonable because NDEBUG is already set (or unset) to take the same effect.

Changed 5 years ago by viboes

Attachment: 7028.patch added

Is this patch enough?

comment:3 Changed 5 years ago by viboes

Owner: changed from No-Maintainer to viboes
Status: newassigned

comment:4 Changed 5 years ago by Eric Niebler

I'm opposed to the suggested resolution, until I hear a better reason. If you don't want your assert handler invoked in release builds, then don't define BOOST_ENABLE_ASSERT_HANDLER. Simple.

As the code is now, it is possible to turn BOOST_ASSERT into something like an ENSURE macro that leaves the checks in, even for release builds. This is important in safety-critical applications -- exactly the same applications where a custom assert handler makes the most sense.

comment:5 in reply to:  4 Changed 5 years ago by viboes

Replying to eric_niebler:

I'm opposed to the suggested resolution, until I hear a better reason. If you don't want your assert handler invoked in release builds, then don't define BOOST_ENABLE_ASSERT_HANDLER. Simple.

As the code is now, it is possible to turn BOOST_ASSERT into something like an ENSURE macro that leaves the checks in, even for release builds. This is important in safety-critical applications -- exactly the same applications where a custom assert handler makes the most sense.

What prevents the users to use the test directly in their code. What am I missing?

Last edited 5 years ago by viboes (previous) (diff)

comment:6 Changed 5 years ago by viboes

Sorry, I have missed the history of this library. IUUC now the introduction of BOOST_ASSERT_MSG in [68414] introduce the defined(NDEBUG)

#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)

  #define BOOST_ASSERT_MSG(expr, msg) ((void)0)

which made BOOST_ASSERT_MSG to behave differently than BOOST_ASSERT.

The introduction of BOOST_VERIFY using

#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )

made also a difference.

So should we remove the use of defined(NDEBUG) and update the documentation of BOOST_ASSERT_MSG?

comment:7 Changed 5 years ago by Mathias Gaunard

I'd rather BOOST_ASSERT be modified to behave like BOOST_ASSERT_MSG does. I see to no reason to have to depend on a BOOST_DISABLE_ASSERTS macro when NDEBUG exists precisely for that purpose.

comment:8 Changed 5 years ago by Eric Niebler

NDEBUG does what it is supposed to, except when BOOST_ENABLE_ASSERT_HANDLER is defined. That's how it's supposed to work. If you are building with NDEBUG defined and you want assertions removed, then don't define BOOST_ENABLE_ASSERT_HANDLER. Why would you, anyway?

comment:9 in reply to:  7 Changed 5 years ago by viboes

Type: BugsFeature Requests

Replying to mgaunard:

I'd rather BOOST_ASSERT be modified to behave like BOOST_ASSERT_MSG does. I see to no reason to have to depend on a BOOST_DISABLE_ASSERTS macro when NDEBUG exists precisely for that purpose.

I don't know what will be the outcome of this issue, but BOOST_ASSERT implementation corresponds to the documentation, so I think that this must be handled as a feature request.

comment:10 Changed 5 years ago by viboes

Owner: changed from viboes to Peter Dimov
Status: assignednew

comment:11 Changed 5 years ago by Mathias Gaunard

BOOST_ENABLE_ASSERT_HANDLER is a global flag (if asserts occur, I need to handle them in a specific way), while disabling assertions is a flag dependent on the build type. Both are orthogonal things.

comment:12 Changed 5 years ago by Eric Niebler

Mathias, can you explain why you would define BOOST_ENABLE_ASSERT_HANDLER when you don't want assertions?

comment:13 Changed 5 years ago by Mathias Gaunard

If assertions occur, I need to print them or log them in a specific way. There is independent from whether assertions are enabled or not and is handled by different parts of my build system

comment:14 Changed 5 years ago by Eric Niebler

IMO, "Because it makes my particular build setup simpler," isn't reason to change a long-standing and well-documented behavior. But I'll leave that for Peter to decide and quit this discussion.

Regardless, BOOST_ASSERT and BOOST_ASSERT_MSG must be made consistent.

comment:15 in reply to:  14 Changed 5 years ago by Steven Watanabe

Replying to eric_niebler:

Regardless, BOOST_ASSERT and BOOST_ASSERT_MSG must be made consistent.

I agree, but...

The only way to make it completely consistent is for BOOST_ASSERT_MSG to be implemented in terms of assert.

#define NDEBUG
#include <boost/assert.hpp>
#undef NDEBUG
#include <cassert>

(I actually favor implementing BOOST_ASSERT_MSG using assert anyway, as I rather dislike the fact that boost/assert.hpp #includes <iostream>)

comment:16 Changed 5 years ago by Peter Dimov

Interesting point Steven. What do you have in mind? The classic assert( expr && "message" )?

Regarding the main point: the original purpose of BOOST_ASSERT was to be exactly equivalent to assert unless overridden by one of the other macros. So, when nothing is defined, it maps to assert, and hence honors NDEBUG. When BOOST_DISABLE_ASSERTS is defined, this is taken as a request to disable BOOST_ASSERT, even when the ordinary asserts are active; and when BOOST_ENABLE_ASSERT_HANDLER is defined, for consistency, this is taken as a request "route all BOOST_ASSERT macros to this handler, even when the ordinary asserts are inactive".

I can certainly see that in some use cases it is more convenient to make it do nothing in NDEBUG configurations even when BOOST_ENABLE_ASSERT_HANDLER is defined. Specifically, when BOOST_ASSERT is used as a library on its own. Its original purpose, however, was to provide a way for Boost libraries to use assertions in a way that can be controlled and overridden by the end user. Hence the current behavior.

comment:17 Changed 4 years ago by Peter Dimov

Resolution: wontfix
Status: newclosed

comment:18 Changed 4 years ago by Peter Dimov

Resolution: wontfix
Status: closedreopened

comment:19 Changed 4 years ago by Peter Dimov

I've added support for the new macro BOOST_ENABLE_ASSERT_DEBUG_HANDLER, which works as requested. It disables assertions when NDEBUG is defined, and is equivalent to BOOST_ENABLE_ASSERT_HANDLER otherwise.

https://github.com/boostorg/assert/commit/f0e5bd15fb70c07ec943d01dc99aa4e507ceffe5

This commit also redefines BOOST_ASSERT_MSG(expr,msg) as assert((expr)&&(msg)) by default, for consistency with BOOST_ASSERT. I'm open to suggestions as to how to optionally provide the old behavior of BOOST_ASSERT_MSG, suitably extended to BOOST_ASSERT as well.

comment:20 Changed 4 years ago by chris.cooper@…

I think assert_test.cpp needs changed too?

comment:21 in reply to:  20 Changed 4 years ago by chris.cooper@…

Replying to chris.cooper@…:

I think assert_test.cpp needs changed too?

Sorry, assert_test.cpp compiles just fine. I'm just confused on your intended usage ... in the patched version, line 59 looks like this:

#if defined(BOOST_DISABLE_ASSERTS)
( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) )

so if I'm creating a release build (NDEBUG is defined) and I haven't defined BOOST_DISABLE_ASSERTS, then by defining BOOST_ENABLE_ASSERT_DEBUG_HANDLER, it disables BOOST_ASSERT_MSG (by #defining it to (void)0). So by defining a macro whose name contains ENABLE, I am disabling the ASSERT functionality?

comment:22 Changed 4 years ago by Peter Dimov

In NDEBUG builds, when nothing else is defined, BOOST_ASSERT_MSG(expr, msg) is defined as assert((expr)&&(msg)), which is also the equivalent of ((void)0). So defining BOOST_ENABLE_ASSERT_DEBUG_HANDLER doesn't disable it any further.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as reopened The owner will remain Peter Dimov.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.