0

私はこのコードを持っています

TSql = class
  private
    FConnString: TStringList;
  public
    property ConnString: TStringList read FConnString write FConnString;
    constructor Create;
    destructor Destroy;
  end;

var 
  Sql: TSql;

...

implementation

{$R *.dfm}

constructor TSql.Create;
begin
  //inherited Create;
  FConnString:=TStringList.Create;
end;

destructor TSql.Destroy;
begin
  FConnString.Free;
  //inherited Destroy;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Sql.Create;
  Sql.ConnString.Add('something');
  showmessage(Sql.ConnString.Text);
  Sql.Destroy;
end;

ボタンを押した後、FConnString を作成するとメモリ リークが発生するのはなぜですか?

................................................................... ................................................................... ...................................................

4

4 に答える 4

11

私が見るものは2つあります。最初のものは、デストラクタの「オーバーライド」の欠如に関する他のコメントと回答ですでにカバーされていました。

2 番目の問題は、プロパティ宣言そのものです。一般に、"write" 句でオブジェクト フィールドを参照するプロパティを宣言しないでください。その理由は、そのプロパティに割り当てると、そのフィールドの既存のインスタンスが「リーク」するためです。プロパティ宣言の「書き込み」句にメソッドを使用します。

property ConnString: TStringList read FConnString write SetConnString;
...
procedure TSql.SetConnString(Value: TStringList);
begin
  FConnString.Assign(Value);
end;

また、このメソッドは FConnString フィールドも上書きしないことに注意してください。Value TStringList の「値」または「コンテンツ」を FConnString インスタンスにコピーするだけです。このようにして、TSql インスタンスはそのフィールドの有効期間を完全かつ完全に制御します。Value TStringlist の有効期間を制御するのは、そのプロパティを割り当てるコードの役割です。

于 2014-05-28T16:47:43.100 に答える
1

指定子で宣言Destroy()するのを忘れたため、オブジェクトが破棄されたときに実際には呼び出されていません。overrideTSql.Destroy

destructor Destroy; override;
于 2014-05-28T16:12:07.933 に答える
0

オブジェクトが正しく作成されていません。それは違いない:

Sql:=TSql.Create;

ここからメモリリークが発生します。

于 2014-05-28T16:36:58.447 に答える