How to override assert macro in C?

assert override purpose
assert c
c assert with message
ndebug
cassert
assert macro in embedded systems
learn cpp assert
assertion error in c++

I want to create my own version of assert in which it does some log prints in case assert was called in NDEBUG mode.

I tried to do the LD_PRELOAD trick and redefine the assert macro but it seems to ignore the macro definition completely and overriding __assert_fail is irrelevant since it isn't called in case of NDEBUG.

How can I override the libc assert macro?

I do not want to create a different function since assert is already used heavily in the project.

An attempt to try to override the assert() macro in a large codebase can be difficult. For example, suppose you have code like:

#include <assert.h>
#include "my_assert.h"
#include "foo.h" // directly or indirectly includes <assert.h>

After this, any use of assert() will again use the system assert() macro and not the one that you have defined in "my_assert.h" (this is apparently part of the C design of the assert macro).

There are ways to avoid this, but you have to use nasty tricks like putting your own assert.h header in the include path before the system assert.h, which is somewhat error prone and non-portable.

I'd recommend using a different named macro than assert, and use regex tricks or a clang-rewriter to rename the various assert macros in your codebase to an assert macro that you can control. Example:

perl -p -i -e 's/\bassert\b *\( */my_assert( /;' `cat list_of_filenames`

(then adding "my_assert.h" or something like it to each of the files modified)

How to Define Your Own assert() Macro for Embedded Systems, I tried to do the LD_PRELOAD trick and redefine the assert macro but it seems to ignore the macro definition completely and overriding __assert_fail is irrelevant  In other words, it can be used to add diagnostics in your C program. Declaration. Following is the declaration for assert() Macro. void assert(int expression); Parameters. expression − This can be a variable or any C expression. If expression evaluates to TRUE, assert() does nothing.

Had the same problem using gcc on Cygwin/Windows and on Linux.

My solution is to overwrite the (weak) definition of the actual assertion failed handling function. Here is the code:

/*!
 * Overwrite the standard (weak) definition of the assert failed handling function.
 *
 * These functions are called by the assert() macro and are named differently and
 * have different signatures on different systems.
 * - On Cygwin/Windows its   __assert_func()
 * - On Linux its            __assert_fail()
 *
 * - Output format is changed to reflect the gcc error message style
 *
 * @param filename    - the filename where the error happened
 * @param line        - the line number where the error happened
 * @param assert_func - the function name where the error happened
 * @param expr        - the expression that triggered the failed assert
 */
#if defined( __CYGWIN__ )

void __assert_func( const char *filename, int line, const char *assert_func, const char *expr )

#elif defined( __linux__ )

void __assert_fail ( const char* expr, const char *filename, unsigned int line, const char *assert_func )

#else
# error "Unknown OS! Don't know how to overwrite the assert failed handling function. Follow assert() and adjust!"
#endif
{
    // gcc error message style output format:
    fprintf( stdout, "%s:%d:4: error: assertion \"%s\" failed in function %s\n",
             filename, line, expr, assert_func );

    abort();
}

Can I override assert macro? - C++ Forum, I generally assume that no assertions appear in header files, though some C++ users may find a need for this. I use the following macro to ensure  The assert macro doesn't even compile for me using GCC, because it says that the macro only has 1 parameter, but I'm trying to pass in 2. Dec 14, 2019 at 10:19pm UTC dutch (1023)

It is a pretty simple thing to do, since assert is a macro. Given that you have this code:

#define NDEBUG
#include <assert.h>

int main( void )
{
  assert(0);

  return 0;
}

Then just do:

#ifdef NDEBUG
#undef assert
#define assert(x) if(!(x)){printf("hello world!");} // whatever code you want here
#endif

Note that this has to be done after #include <assert.h> though.

So if you want to stick your own definition into a common header file, and then use that header file to modify existing code, then your header file have to be included after assert.h.

my_assert.h

#include <assert.h>
#include <stdio.h>

#ifdef NDEBUG
#undef assert
#define assert(x) if(!(x)){printf("hello world!");}
#endif

main.c

#define NDEBUG    
#include <assert.h>
#include "my_assert.h"

int main( void )
{
  assert(0); // prints "hello world!"
  assert(1); // does nothing

  return 0;
}

assert - cppreference.com, JLBorges, I like your usage better than what I found at cppreference, with the #​define. In Visual Studio 2017/2019 using the comma operator  If the argument of the MFC ASSERT macro evaluates to zero or false, the macro halts program execution and alerts the user; otherwise, execution continues. When an assertion fails, a message dialog box shows the name of the source file and the line number of the assertion. If you choose Retry in the dialog box,

The C99 rationale provides a sample on how to redefine the assert in a good way on page 113:

#undef assert
#ifdef NDEBUG
#define assert(ignore) ((void)0)
#else
extern void __gripe(char *_Expr, char *_File, int _Line, const char *_Func);
#define assert(expr) \
((expr) ? (void)0 :\
 __gripe(#expr, _ _FILE_ _,_ _LINE_ _,_ _func_ _))
#endif 

I'd include assert.h right before this code to make sure assert.h is used. Also notice that it calls a function that would do reporting logic, so that your code would be smaller.

Custom assert Macro in C / C++ with __LINE__ and , The definition of the macro assert depends on another macro, NDEBUG, which is not defined by the standard library. If NDEBUG is defined as a  Assertion violation: file tripe.c, line 34: size <= LIMIT. if size is greater than LIMIT. Preconditions. Preconditions specify the input conditions to a function. Here is an example of a function with preconditions: int magic( int size, char *format ) { int maximum; assert( size <= LIMIT ); assert( format != NULL ); These pre-conditions have two consequences:

You can check if NDEBUG is defined and if it is then print whatever logs you want to print.

Consistency Checking (The GNU C Library), The ability to print out its own location is not a built in language feature of assert. Any programmer can replicate this behavior using the macros __  So, the macro has to arrange for each usage to get a unique type name to declare. My usual solution has been to require that the macro have two parameters. The first is the condition to assert is true, and the second is part of the type name declared behind the scenes.

C/C++ Assertions and Defining Your Own Assert Macro, The assert macro, defined in the header file assert.h , provides a convenient way to abort the program while printing a message about where in the program the  at the beginning of the code, before the inclusion of <assert.h>. Therefore, this macro is designed to capture programming errors, not user or run-time errors, since it is generally disabled after a program exits its debugging phase. Parameters expression Expression to be evaluated.

rg3/xassert: C/C++ custom assertion macros, Regular C assert is just fine and dandy but there are many possible reasons for wanting to write a custom macro. Maybe you want to log failed  Compile and link the file with your reimplementation (override.c). This allows you to override a single function from any source file, without having to modify the code. The downside is that you must use a separate header file for each file you want to override.

assert.h, xassert is a set of C/C++ custom assertion macros. To use them, include stdlib.h or cstdlib followed by xassert.h and call ASSERT, DASSERT, XASSERT or  C Language: assert macro (Assert Truth of Expression) In the C Programming Language, assert is a macro that is designed to be used like a function. It checks the value of an expression that we expect to be true under normal circumstances. If expression is a nonzero value, the assert macro does nothing.

Comments
  • Assert is a macro, so the LD_PRELOAD trick isn't applicable. You will need to undefine the standard macro (or not include the header file that defines it), and then define your own assert macro before including any of the other headers that use it. If the code is already compiled into a library, it is too late.
  • I do not want to create a different function since assert is already used heavily in the project. It's not a problem if you use a text editor from 1980th or more recent. Refactor->rename or grep and diff/VCS might save you a lot of troubles and will allow you to avoid inventing ugly hacks.
  • Why not just add code to local assert.h and add it's path to CPPFLAGS? It would then override system assert.h.
  • That requires confidence and testing, to ensure that all the compilers in use (or that may be used) will allow an override of a system header using -I. When I wrote this answer, I worked on a product built on 11 platform variations with a number of compilers. I wouldn't have had the confidence to try that with our product.
  • Well, I haven't seen a single compiler which wouldn't allow override of system headers via -I (including Visual Studio) and I don't believe there are reasons why such compiler would exist...
  • When NDEBUG is defined, assert will expand to nothing and underlying function will not be called.
  • Yes. Thats the expected behaviour. So the solution works consistent to the "standard" behaviour.
  • But OP asked about overloading assert in NDEBUG case: "I want to create my own version of assert ... in case assert was called in NDEBUG mode".
  • Aaah, you're right. I didn't understand the in NDEBUG mode from the original question. So if NDEBUG is defined then indeed this solution will not help at all. It is only usefull in case you need to customize the format or the target (file/socket/...) of the assertion failed messages. Sorry for my misunderstanding.
  • As a side note, I'm rather sure that, formally and pedantically, #undef of a library macro is UB. In this specific case, there is no reason why it shouldn't work though.
  • Slight nit pick but #define assert(x) do{ if(!(x)){printf("hello world!"); }} while(0) is better because then semicolons work as expected
  • @JeremyP No, that's a bad idea. That way you will not get compiler errors when someone uses your code like if(x) assert(something); else with no braces. You should never write if statements without braces (ask Apple if doing so was a good idea). If your macro forces the user to write safer C, your macro is doing good things. "do-while-zero" macros are as obsolete as the "yoda conditions" and other such nonsense tricks from the 1980s.
  • This solution requires replacing of #include <assert.h> to #include <assert.h> #include "my_assert.h" in every source file where assert is used. This way, simple textual replacement of all instances of assert to a custom macro would probably be easier and more robust.
  • @LundinIt is equally not the purpose of SO to police coding style. asset() looks like a function, it should behave like a function syntactically and not cause unexpected syntax errors in otherwise legal situations. Your version of assert() is therefore not high quality code or, at least, not as high quality as it could be.