How does a memory manager usually work? Initially, there is a large chunk of memory that you can work with, and which is marked as free. When requested, the manager can, for example, allocate a piece of memory and keep a note in his internal list - this memory is allocated, do not touch it ... (in fact, this is a separate and very serious topic, but such an idea will suffice for explanation) . The block is released - the manager makes a corresponding mark on himself. Most likely, in front of the block there will be a small block with service information - about employment, the size of the occupied block, etc.
What happens when you release with the memory itself? Nothing. It is simply marked as free. Only the information in the service fields is changing.
Therefore, you can write there information. Or take it.
But even if you do it right after being released, without intermediate actions - no one can guarantee you the correctness of this action: what if the same manager writes his official information to this place, so you just spoil it? Or another thread will have time to capture this memory yourself? Nobody knows what exactly will happen, so about such situations it is said - “indefinite behavior”.
In short, getting a program crash in such a situation is more like luck. Bad luck - not to get any error, but to mess up the memory, and then, after 15 minutes of the program's work, get into trouble - for example, a completely incorrect value of a variable that you seem to have saved as something completely different. And then for a long time - to look for a mistake for a very long time, which is located in a completely different place of the program, and it also does not reproduce completely at every launch ...