During my tests, I have found that it is possible to use pointer after free(). I have the following code:
typedef struct{
int module_id;
int adc_id;
Because the memory is still mapped into your process, but isn't allocated. There are two levels of memory management that go on in a C program: Firstly, the kernel gives you pages you can write to. If the process needs more memory that it has mapped, it has to request more from the kernel (sbrk). That comes in large chunks though, so malloc slices it up into chunks for you, requesting more pages as needed, but using where possible memory already allocated to the program. free can't return a page until all the allocations that used it have been freed.
So, the memory access violations the kernel gives you (SIGSEGV) are rather coarse, and can't pick up most memory errors, only things that are fatal from a kernel point of view. You're free to trash your malloc's tracking data, read past the end of most allocations and after many frees, and so on.
Don't ever commit memory errors though. Run your app with valgrind, which uses a very strict VM, to check for all errors and squash them immediately.