Reading/writing memory after it has been free()ed.
Reading/writing off the end of malloc()ed blocks.
Reading/writing inappropriate areas on the stack.
Memory leaks -- where pointers to malloc'd blocks are lost
forever.
Passing of uninitialized and/or unaddressable memory
to system calls.
Mismatched use of malloc()/new/new [] vs
free()/delete/delete [].
Some abuses of the POSIX pthreads API.
valgrind is very easy to use. It has many optional flags that you can learn
about from the documentation. (valgrind -h).
A useful flag is --num-callers=NNN
which sets how far back to print the function call sequence when an error
is detected, (sometimes the error actually occurs in a sequence of functions
you didn't write). By default it is --num-callers=4.