Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `assert` macro have value even with `NDEBUG`?

Tags:

c++

c

Environment:

$ g++ --version
g++ (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0

It is known that function-like macro assert for debugging can be disabled with NDEBUG defined before the include of assert.h (cassert). However, reading /usr/include/assert.h in my environment, I found the code below.

#if defined __cplusplus && __GNUC_PREREQ (2,95)
# define __ASSERT_VOID_CAST static_cast<void>
#else
# define __ASSERT_VOID_CAST (void)
#endif

#ifdef  NDEBUG

# define assert(expr)       (__ASSERT_VOID_CAST (0))

# ifdef __USE_GNU
#  define assert_perror(errnum) (__ASSERT_VOID_CAST (0))
# endif

#else /* Not NDEBUG.  */

So, even with NDEBUG, assert is expanded into some value and thus affect the performance insignificantly but certainly (if no optimization occurs after the preprocess step). Since C++ standard allows function-like macro with empty value, it seems

#ifdef NDEBUG
#define assert(expr)
#endif

would be a good implementation.

Is there any reason why non-empty value should be the option?

like image 215
ynn Avatar asked May 23 '19 04:05

ynn


People also ask

What is the purpose of the assert () macro?

The assert() macro is used to check expressions that ought to be true as long as the program is running correctly. It is a convenient way to insert sanity checks.

How does assert () work?

The assert() function tests the condition parameter. If it is false, it prints a message to standard error, using the string parameter to describe the failed condition. It then sets the variable _assert_exit to one and executes the exit statement. The exit statement jumps to the END rule.

What is assert () in C++?

Answer: An assert in C++ is a predefined macro using which we can test certain assumptions that are set in the program. When the conditional expression in an assert statement is set to true, the program continues normally. But when the expression is false, an error message is issued and the program is terminated.

Is assert a macro?

The assert macro prints a diagnostic message when expression evaluates to false (0) and calls abort to stop program execution. No action is taken if expression is true (nonzero). The diagnostic message includes the failed expression, the name of the source file and line number where the assertion failed.


1 Answers

One reason that the macro has a value when NDEBUG is defined is because the C standard requires that it has one — it even stipulates what it shall be.

C11

§7.2 Diagnostics <assert.h>

¶1 The header <assert.h> defines the assert and static_assert macros and refers to another macro,

    NDEBUG

which is not defined by <assert.h>. If NDEBUG is defined as a macro name at the point in the source file where <assert.h> is included, the assert macro is defined simply as

    #define assert(ignore) ((void)0)

The assert macro is redefined according to the current state of NDEBUG each time that <assert.h> is included.

¶2 The assert macro shall be implemented as a macro, not as an actual function. If the macro definition is suppressed in order to access an actual function, the behavior is undefined.

7.2.1.1 The assert macro

Synopsis

    #include <assert.h>
    void assert(scalar expression);

Description

¶2 The assert macro puts diagnostic tests into programs; it expands to a void expression. When it is executed, if expression (which shall have a scalar type) is false (that is, compares equal to 0), the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function -- the latter are respectively the values of the preprocessing macros __FILE__ and __LINE__ and of the identifier __func__) on the standard error stream in an implementation-defined format.191) It then calls the abort function.

Returns

¶3 The assert macro returns no value.

191) The message written might be of the form:

Assertion failed: expression, function abc, file xyz, line nnn.

C++11

The C++11 standard says (§19.3 Assertions) says:

The header <cassert> … provides a macro for documenting C++ program assertions and a mechanism for disabling the assertion checks.

The contents are the same as the Standard C library header <assert.h>.

So the same rules apply to C++ as to C. The C++ standard doesn't explicitly call out the differences between the C++ static_assert and the C _Static_assert (and the definition of static_assert as _Static_assert in the C version of the <assert.h> header). The net result is much the same, though.

like image 158
Jonathan Leffler Avatar answered Oct 04 '22 01:10

Jonathan Leffler