4

After reading this I would like to know what is the problem with the next code:


procedure TForm1.Button5Click(Sender: TObject);
begin
  Button5.free;
end;
Community
  • 1
  • 1
Najem
  • 537
  • 4
  • 12
  • That was one of the questions of our standard job interview few years ago `delete(this)` in C++ terms. – PA. Mar 29 '11 at 14:47
  • 1
    PA, not *exactly* the same thing... self in this case is Form1, not Button5, but call stack contains return points where self is Button5. – jachguate Mar 29 '11 at 15:08

2 Answers2

5

Put a breakpoint on that routine and examine the call stack. Once you return from the event handler, there's still code from Button5 running, and other VCL code that expects Button5 to still be around. If you delete the object out from under it, there's a good chance that you'll end up corrupting memory or raising exceptions somehow.

If you want to do this, the correct way is to call PostMessage and post a message to the form that will end up freeing the object safely after the current code is finished running.

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
1

The code is a worst kind of a bug because it does not reveal itself in 99.99% of cases. You free an object (button control) while VCL assumes the object exists. What actually happen is that the object's memory is freed, but not reused yet, so the above code will work OK, as if the object was not freed yet, but still it is a bug.

The following simple bug illustrates the situation:

type
  PData = ^TData;
  TData = record
    Value: Integer;
  end;

procedure NastyBug;
var
  P: PData;

begin
  New(P);
  P^.Value:= 2;
  Dispose(P);
// nasty buggy code
  ShowMessage(IntToStr(P^.Value));
  P^.Value:= 22;
  ShowMessage(IntToStr(P^.Value));
end;

You can test the above code and it should work as expected, because the disposed memory for P is not reused yet, but the code is a clear bug.

kludg
  • 27,213
  • 5
  • 67
  • 118