I was thinking about the same thing quite a while ago. The key issue with "crashing intentionally" is: Almost any code that would crash in practice is just "undefined behavior" according to the C standard, and a compiler could always detect it and do something (anything!) else. Also, optimizers might remove the "crash reason" accidentally
Many modern compilers support
__builtin_trap()
for that purpose, but it's not standard C. So this is your best bet. While crashing accidentally is quite easy, crashing intentionally is, strictly speaking,
impossible to do reliably in standard C.
Back then, I came up with the following code:
Code:
#undef HAVE_BUILTIN_TRAP
#ifdef __GNUC__
# define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
# if GCC_VERSION > 40203
# define HAVE_BUILTIN_TRAP
# endif
#else
# ifdef __has_builtin
# if __has_builtin(__builtin_trap)
# define HAVE_BUILTIN_TRAP
# endif
# endif
#endif
#ifdef HAVE_BUILTIN_TRAP
# define crashMe() __builtin_trap()
#else
# include <stdio.h>
# define crashMe() do { \
int *volatile iptr = 0; \
int i = *iptr; \
printf("%d", i); \
abort(); } while (0)
#endif
This defines a macro
crashMe()
to force a crash. It checks for
__builtin_trap()
support using
__has_builtin()
and also checks the GCC version (for some old GCC versions that support
__builtin_trap()
, but not
__has_builtin()
to detect it).
When compiled with a compiler that doesn't have the required builtin, it uses some "best effort" code instead:
- Use
volatile
, so the read access for dereferencing the null pointer can't be optimized away.
- Use
printf()
so there is a side effect, forcing the compiler to keep the i
variable and actually execute the code.
- Still add
abort()
to at least have an unclean exit in cases the compiled code somehow makes it there without crashing
edit: A little additional remark: This "best effort" code of course has
undefined behavior as well, so, although it tries to ensure a crash, this is not guaranteed. It might just do an unclean exit (
abort()
) or might even do something completely different. Sure, the famous nasal demons are somewhat unlikely

– but it might just, for example, never terminate.
Nothing to worry about with a recent gcc or clang though, both support
__builtin_trap()
.