Вызов aControl.free внутри aControl - PullRequest
4 голосов
/ 29 марта 2011

После прочтения this хотелось бы узнать, в чем проблема со следующим кодом:


procedure TForm1.Button5Click(Sender: TObject);
begin
  Button5.free;
end;

Ответы [ 2 ]

5 голосов
/ 29 марта 2011

Установите точку останова в этой подпрограмме и проверьте стек вызовов.Как только вы вернетесь из обработчика событий, все еще будет работать код из Button5 и другой код VCL, который ожидает, что Button5 все еще будет.Если вы удалите объект из-под него, есть большая вероятность, что вы испортите память или вызовете какие-то исключения.

Если вы хотите сделать это, правильный способ - вызвать PostMessage и опубликоватьсообщение в форму, которое приведет к безопасному освобождению объекта после завершения работы текущего кода.

1 голос
/ 29 марта 2011

Код является худшим видом ошибки, потому что он не обнаруживает себя в 99,99% случаев. Вы освобождаете объект (управление кнопкой), пока VCL предполагает, что объект существует. На самом деле происходит то, что память объекта освобождается, но еще не используется, поэтому приведенный выше код будет работать нормально, как если бы объект еще не был освобожден, но все же это ошибка.

Следующая простая ошибка иллюстрирует ситуацию:

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;

Вы можете протестировать приведенный выше код, и он должен работать, как и ожидалось, поскольку выделенная память для P еще не используется повторно, но код является явной ошибкой.

...