In standard C99, this (dereferencing (int*)2
in your *p =3;
statement) is undefined behavior (UB). Read C.Lattner's blog on that. You should be very scared of UB. This is why programming in C is so hard (other programming languages like Ocaml, Common Lisp have much less UB).
A C program may have undefined behavior but might not always crash.
In practice, when coding in C, be vary careful about pointers. Initialize all of them explicitly (often to NULL
). Be very careful about pointer arithmetic. Avoid buffer overflows and memory leaks. Static source code analysis may help (e.g. with Frama-C) but is limited (read about halting problem & Rice's theorem). You could use quite often flexible array members and check pointers and indexes at runtime.
On some embedded freestanding C implementations (e.g. coding for Arduino like devices), some addresses might have particular meanings (e.g. be some physical IO devices), hence UB could be very scary.
(I am focusing on Linux below)
On some implementations, and some operating systems, you might test if an address is valid. For example on Linux you might parse /proc/self/maps
to compute if some given address is valid (see proc(5) for more about /proc/
).
(therefore, you could write -on Linux- some function bool isreadableaddress(void*)
which would parse /proc/self/maps
and tell if an address is readable in the virtual address space of your process; but it won't be very efficient since needing several system calls)
And you should use valgrind and compile with all warnings & debug options (gcc -Wall -Wextra -g
) and use the debugger (gdb
) and some more debugging compiler options like -fsanitize=address
You might perhaps handle the SIGSEGV
signal, but it is very tricky and highly non-portable (operating system, processor, and ABI specific). Unless you are a guru, you should not even try.