3

I have this code in a VCL Forms Application:

implementation

{$R *.dfm}

var
  MyBitmap: TBitmap;

procedure TFormMain.FormCreate(Sender: TObject);
begin
  MyBitmap := TBitmap.Create;
end;

procedure TFormMain.FormDestroy(Sender: TObject);
begin
  if Assigned(MyBitmap) then
    MyBitmap.Free;
end;

procedure TFormMain.Button1Click(Sender: TObject);
begin
  if Assigned(MyBitmap) then
    MyBitmap.Free;
end;

When I click the button the second time I get an Access violation in MyBitmap.Free; in the button's click handler. But MyBitmap shouldn't be anymore assigned after the first button click. So why the condition if Assigned(MyBitmap) then does not work on the second button click when it obviously did work on the first button click?

Delphi 10.1 Berlin Update 2

user1580348
  • 5,721
  • 4
  • 43
  • 105
  • 1
    Assigned checks for being equal to nil, freeing an object reference does not make it nil. Hence you are attempting a double free. – Sertac Akyuz Dec 07 '16 at 17:26
  • It seems that `System.SysUtils.FreeAndNil(MyBitmap)` does the job without AV. – user1580348 Dec 07 '16 at 17:31
  • So, conclusively we have learned: An OBJECT can be RELEASED with `FREE` and an OBJECT VARIABLE can be SET to `NIL`, not vice-versa. Is this correct? – user1580348 Dec 07 '16 at 17:48
  • What exactly happens when `MyObject.Free` is executed? Is the memory for the object explicitly released? How exactly is it released? What does this mean in practice? – user1580348 Dec 07 '16 at 17:54
  • Practically you could say that freeing is responsible for releasing resources that is acquired for the object, including memory. – Sertac Akyuz Dec 07 '16 at 17:56
  • What does "releasing" exactly mean? Does it tell Windows that the memory space previously occupied by `MyObject` is not needed anymore and can now be used for other purposes? – user1580348 Dec 07 '16 at 17:59
  • Yep. Practically though, the probability is higher that the memory manager reserves unused space, for later use, instead of giving it back to the OS. – Sertac Akyuz Dec 07 '16 at 18:05
  • Is the "memory manager" a feature of the program or a feature of Windows? – user1580348 Dec 07 '16 at 18:17
  • http://docwiki.embarcadero.com/RADStudio/en/Memory_Management – Sertac Akyuz Dec 07 '16 at 18:19
  • Related: http://stackoverflow.com/questions/8548843/why-should-i-not-use-if-assigned-before-using-or-freeing-things – David Heffernan Dec 07 '16 at 18:55

1 Answers1

7

The Assigned function only checks the pointer to be Nil. It doesn't perform a check whether the it's pointing to an existing object or not. You need to set it to Nil after freeing it in order to get the Assigned function work as you expect it. FreeAndNil performs both instructions.

Wosi
  • 41,986
  • 17
  • 75
  • 82
  • Is there a common rule for when to use `Free` and when to use `FreeAndNil` when releasing an object variable? – user1580348 Dec 07 '16 at 17:35
  • @user - If there is a probability that an object can be freed from multiple places, FreeAndNil can be useful. But that's not very common. – Sertac Akyuz Dec 07 '16 at 17:58
  • 2
    This is opinion based. IMHO you should set the object reference to `Nil` after freeing it when the variable can be accessed after the referenced object has been freed. So you don't need to `Nil` local variables in a method when there is nothing about to happen after the `Free`. Nobody can access these variables afterwards. The same applies for object references stored in member variables of a class and which are freed in its destructor. But you should `Nil` them additionaly when you `Free` them during the lifetime of that object (e.g. freeing a form's member inside a button click). – Wosi Dec 07 '16 at 18:11