Hi,
1) Handling of dynamic memory is not done by compiler. There are run-time libraries which take care of this. For eg. : glibc provides APIs like malloc and free, which internally make system calls(sys_brk) to handle the heap area.
2) Freeing same memory twice refers to a condition like this :
Suppose you have char *cptr;
You allocate memory using :
cptr = (char *) malloc (SIZE);
Now, when you no longer need this memory, you can free it using this :
free(cptr);
Now here what happens is the memory pointed to by cptr is free for use.
Suppose at a later point of time in the program you again call a free(cptr), then this is not a valid condition. This scenario where you are freeing the same memory twice is know as "freeing a memory twice" problem.`