Нарушение доступа при освобождении формы в событии OnDestroy другой формы - PullRequest
0 голосов
/ 24 апреля 2018

Я работаю над Delphi 7. Я получаю ошибку нарушения доступа при освобождении формы.

1) Создать новое приложение Delphi 7 (Unit1)

2) Добавить новую форму (Unit2)

3) Для Unit1 использует предложение добавить Unit2 и написать ниже код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, unit2, StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  form2 : TForm2;
begin
  try
    form2 := TForm2.Create(Application);
    //form2.ShowModal;
  finally
    //FreeAndNil(form2);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Form2 <> nil then
    FreeAndNil(form2);
end;

end.

4) Запустите приложение и закройте форму Form1 - Ошибка ниже.

enter image description here

Я не хочу освобождать Form2Объект на OnClose или OnCloseQuery, потому что у меня есть код для этих событий. Я хочу освободить объект Form2 после OnClose или OnCloseQuery.

почему я получаю ошибку и как это исправить?

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Описанную проблему можно воспроизвести в Delphi 7, следуя вашим инструкциям.Причиной нарушения прав доступа является то, что Form2 автоматически создается в файле .dpr (и это делает приложение владельцем формы), но вы также пытаетесь контролировать его время жизни, вызывая FreeAndNil(Form2) в OnDestroyсобытие Form1.Когда вы пытаетесь освободить форму, она уже освобождается приложением.

Не совсем понятно, почему вы пытаетесь освободить Form2, когда приложение (предположительно) собирается завершить работу (так какосновная форма разрушается).Поскольку приложение является владельцем, вы можете спокойно позволить приложению позаботиться о его обязанностях.

Вам необходимо решить, кем вы хотите стать владельцем Form2.

  1. Если это вы, вы должны удалить Form2 из списка автоматически созданных форм (см. Project - Options - Forms и переместить Form2 в Available forms).
  2. Если вы хотите, чтобы приложение было владельцемпросто не Free форму, используйте методы hide и show для контроля ее видимости, если это необходимо, но оставьте это для приложения, чтобы уничтожить его в соответствии с его дизайном.

Кстати, код, который вы имеете в TForm1.FormCreate(), не имеет ничего общего с AV, который вы видели.То, что Form2 является отдельным экземпляром, и если намерение состоит в том, чтобы показать форму всплеска, все в порядке, как показано ниже:

procedure TForm1.FormCreate(Sender: TObject);
var
  form2 : TForm2;
begin
  form2 := TForm2.Create(nil);
  try
    form2.ShowModal;
  finally
    form2.Free;
  end;
end;

Форма не нуждается в владельце, поэтому nil вCreate.Поскольку переменная form2 является локальной, нет нужды ее обнулять.

0 голосов
/ 24 апреля 2018

проблема в том, что Form2 будет объявлено в unit2 и снова в FormCreate этой формы. Вы просто используете не тот.

Я предлагаю удалить объявление Form2 из unit2 и использовать только одно в этом модуле, а также переместить объявление в приватный раздел

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Form2: TForm2; // Declare the form here, not in unit2
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form2 := TForm2.Create(nil);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // no need to check if Form2 exists, it is created in the FormCreate and will thus always exist
  // unless there is code somewhere that we cant see that destroys it.
  // Also no need to set the variable to nil as mentioned in the Tom's answer
  Form2.Free;
end;
...