As a Delphi developer, you don’t get around objects. Creating and freeing them is an essential part of every Object Pascal based application. But now here comes a random guy telling you that you made your whole life a serious mistake at object management! Unbelievable, but hear me out, because you are going to thank me later on.
As you probably already know an object variable is essentially a pointer to the address where the memory for your instance is reserved. So creating an object returns the address and freeing an object marks the reserved memory as “not in use anymore”, but the object variable still contains the address to where the object originally was. And here comes the horror of object management in Delphi!
When you forget to nil the variable after freeing than you don’t know if it’s still valid, but that’s not even the worst that could happen. Imagine you have a business application where it’s critical that everything runs perfectly, but then out of nowhere your objects returns a number you can’t explain. It’s nothing you have ever seen and no one in your company can help you. Even worse; you can’t replicate the bug, but your customer/the user still gets this bug from time to time corrupting his data. I will leave it to your imagination what can happen when you have a 1 instead of a 0 in an application that decides between life and death.
But why can something like that happen just because I forgot to nil an object after freeing it?
The thing is that your program doesn’t care if the reserved memory of your object is valid or not. When it’s able to get what it wants, then it’s happy even if the memory got reserved and overridden by another instance.
This typically results in the well known access violation of reading/writing at address 80070010 (or something similar) and when you see something like this you really should freak out! This is obviously a bug where the application tries to access the memory of an object that got freed and it’s a miracle you accidentally found this because it’s completely random (well, not really random, but depending on your application you can interpret it as random) if this access violation happens.
Hint: An easy way to differentiate between a null-pointer access violation and an access violation because of freed memory is by looking at the address. When the address is a really small number (something like 00000004) then it’s a null-pointer access violation. Otherwise, it’s an access violation because of freed memory.
But how can I fix this memory madness?!
— Random stranger on the Internet
Forget the idea of using .Free! Yeah, it’s the time of object oriented programming, but no one wants bugs or write two lines of code when they can just write one.
So instead of writing
Object.Free; Object := nil; // <- considering you even wrote this line
The thing is that FreeAndNil does nothing more than checking if your object is <> nil and if it is it calls .Free and sets it := nil.
So here is my advice; use FreeAndNil all the times when it’s possible. It’s not going to change the logic but help you find bugs before you deliver them out.
Use FreeAndNil(Object) instead of Object.Free to prevent data corruption and bugs that are gonna break your mind!