You should always free allocated memory before you exit. As already mentioned in other answers, this will minimize warnings from static- or dynamic analysis tools etc.
But the real reason why you should always do this, is because freeing often exposes dormant run-time bugs in your application.
If you have a bug somewhere that causes memory corruption or changes pointer addresses, that bug may stay silent and dormant. Until you change something completely unrelated to the bug and thereby shuffle around the memory layout. Then suddenly you get a crash and you'll have no idea why, because the bug isn't even located in the code you just added.
By freeing the memory, you provoke such bugs to surface. Because if there is anything wrong with the heap or with the pointers pointing at the heap, then you will often get a crash at the point where you call free()
. Which means that you have a severe bug somewhere, that you need to find before shipping the program.