Here you go:
#define abort(msg) (fprintf(stderr, msg) && *((char*)0))
Here you go:
#define abort(msg) (fprintf(stderr, msg) && *((char*)0))
The obvious criticism of that implementation is that it has a different interface from what the C standard requires:
§7.20.4.1 The abort function
Synopsis
#include <stdlib.h> void abort(void);
Description
The
abort
function causes abnormal program termination to occur, unless the signalSIGABRT
is being caught and the signal handler does not return. Whether open streams with unwritten buffered data are flushed, open streams are closed, or temporary files are removed is implementation-defined. An implementation-defined form of the status unsuccessful termination is returned to the host environment by means of the function callraise(SIGABRT)
.Returns
The abort function does not return to its caller.
There were systems, notoriously the DEC VAX, where accessing the memory at address 0 did not cause problems (until the programs that were written on the VAX were ported to other platforms that did abort).
Dereferencing a null pointer is undefined behaviour - that means anything could happen, including 'no crash'.
If, for some reason, fprintf()
returns 0, your program will not abort. For example:
abort("");
does not abort. It is also dangerous to use the string as the format string; you should use:
#define abort(msg) (fprintf(stderr, "%s\n", msg) && *((char*)0))
It would be better to use a comma operator in place of the &&
:
#define abort(msg) (fprintf(stderr, "%s\n", msg), raise(SIGABRT))
Since the standard library could have defined a macro abort()
, you should #undef
it before defining it yourself.
fputs()
is that it does not add a newline to the string (unlike puts()
- but that writes to stdout instead of stderr), so you'd have to call it twice, once with the user string and once with the newline. It seems simpler to call fprintf()
once.
\$\endgroup\$
Oct 16, 2011 at 3:34
fputs
followed by fputc(stderr, '\n')
(and then flush) would be far faster than fprintf
. When you're reporting an error, you usually want to use the most trivial functions possible (lest data corruption prevent them from running) and fputs
and fputc
are much much simpler than fprintf
.
\$\endgroup\$
Oct 16, 2011 at 3:55
My criticism is you are trying to abort via a crash:
*((char*)0))
This invokes undefined behavior. It does not necessarily invoke a crash (or termination).
If you want to raise the abort signal do so explicitly:
raise(SIGABRT)
Also you are re-defing a system method using #define (I am relatively sure this is not allowed and causes undefined behavior though I can not quote chapter and verse).
#define abort(msg)
Also by doing this you need to search through all the source to find any current usage of abort. As this may clash with the new usage (or will the pre-processor be intelligent about it. The fact that I ask the question should make you worry let alone the answer).
Why not define your own function with a slightly different name (this will also allow you to call the system abort).
#define abortWithMsg(msg) do { fprintf(stderr, msg); abort(); } while (false)