In CP/M, it wasn't a matter of freeing memory so much, since you had a static area of RAM for your program, and every program ran in the same space. So, when Program A quit, and Program B ran, B was simply loaded over on top of A.
Now there were mechanisms to reserve memory away from the OS, but this wasn't typically heap memory (in the classic case that we consider it today), it was special reserved areas design for various tasks.
For example, DOS had this exit routine called "Terminate and Stay Resident". This "quit" the program, but didn't not release the space after the program quit. Typically these programs loaded up interrupt vectors (such as keyboard interrupts) to trigger routines. Borland Sidekick was a very popular "TSR" back in the day and offered things like a calculator and contact list.
Finally, since these weren't protected memory systems, your programs could abuse the system in all sorts of ways to do what you want, but that's a different discussion.