6

私は、Delphi について根本的な疑問を 1 つ持っています。設計時にコンポーネントを保持する場合、たとえば TADOConnectuion でボタンをクリックすると、次のコードを記述してもエラーは発生しません。

begin
  ADOConnection.Free;  //No error
  ADOConnection.Free;  //No error
  ADOConnection.Free;  //No error
end;

しかし、実行時に次のように同じオブジェクトを作成すると、「アクセス違反...」エラーが発生します

begin
  ADOConnection := TADOConnection.create(self);
  ADOConnection.Free;  //No error
  ADOConnection.Free;  //Getting an "Access Violation..." error
end;

以下のようにオブジェクトを作成しても、同じエラーが発生します。

ADOConnection := TADOConnection.create(nil);

このような動作の背後にある理由、つまり、設計時にコンポーネントを保持しているときにエラーが発生しない理由を知りたいですか?

4

2 に答える 2

4

コンポーネントを解放すると、所有者の対応するフィールドがクリアされます。design-time を追加するADOConnectionと、

ADOConnection.Free; // Frees ADOConnection and sets ADOConnection to nil
ADOConnection.Free; // Does nothing since ADOConnection is nil

これは、変数にキャプチャすることで確認できます。

var c: TADOConnection;
c := ADOConnection;
c.Free; // Frees ADOConnection and sets ADOConnection to nil
c.Free; // Error: c is not set to nil

ADOConnection設計時に作成された場合でも、それは機能しません。

TButton次に示すのは、デザイン時のコンポーネントで見られる動作がデザイン時のコンポーネントに固有のものではないことを示すコンポーネントの例です。

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  published
    Button: TButton;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Assert(not Assigned(Button));
  TButton.Create(Self).Name := 'Button'; // Button field gets set
  Assert(Assigned(Button));
  Button.Free;                           // Button field gets cleared
  Assert(not Assigned(Button));
  Button.Free;                           // Okay, Free may be called on nil values
end;

end.
于 2012-08-30T09:03:36.823 に答える
3

ADOConnection は最初は nil なので、これを解放すると、渡されたポインターが nil であるため、free 関数は何もしません。以降の呼び出しではポインタは nil のままなので、 free は何もしません。create で ADOConnection を初期化すると、ADOConnection に保持されているポインターは nil ではなくなるため、free の最初の呼び出しでポインターがアクティブに解放されますが、その後の呼び出しでは、メモリが既に解放されていることがわかり、例外が発生します。ポインターは free の呼び出しによって変更されません。そのためには、代わりに freeandnil が必要です。

于 2012-08-30T08:58:14.043 に答える