Delphi - 如何从 TDataSet 中释放内存?

use*_*073 2 delphi memory-leaks tdataset

D2010,Win7 64 位。你好,

我有一个需要处理在另一个例程中打开的 TDataSet 的 buttonClick 事件... GetDBGenericData。

函数 GetDBGenericData 返回一个 TDataSet。该例程基本上采用 tQuery 组件,设置它的 SQL 属性,然后打开它。然后它将 TDataSet 返回给我的 buttonclick。

procedure TForm1.Button2Click(Sender: TObject);
var
DS : TDataSet;
begin

DS := TDataSet.Create(nil);
DS := GetDBGenericData(dbSOURCE, 'LIST_ALL_SCHEMAS', [] );

while Not DS.EOF do
   begin
   ShowMessage(DS.FieldByName('USERNAME').AsString);
   DS.Next;
   end;

DS.Close;
DS.Free;
Run Code Online (Sandbox Code Playgroud)

我的问题是——了解 DS。我在这个例程中在这里创建它。我将它“分配”给一个指向组件的 TDataSet。如果我不释放它,就会出现内存泄漏(如 EurekaLog 报告的那样)。如果我释放它,下次我运行这个程序时我会得到一个 AV。(特别是在 GetDBGenericData 例程中)。

我认为正在发生的是 DS 被分配给(而不是复制)到正在返回的 TDataSet,所以实际上,我在这个例程中释放了两个 DS,以及 GetDBGenericData 中的 tQuery,当我做一个免费的.

如何“中断”链接,然后删除仅与我动态创建的内存关联的内存。

谢谢,GS

Ken*_*ite 5

如果您的DS变量被分配其他TDataSetGetDBGenericData,你既不应该Create还是Free它。您只是使用它来引用现有数据集。

procedure TForm1.Button2Click(Sender: TObject);
var
  DS : TDataSet;
  UserNameField: TField;  // Minor change for efficiency
begin
  DS := GetDBGenericData(dbSOURCE, 'LIST_ALL_SCHEMAS', [] );

  // Call FieldByName only once; no need to create or
  // free this either.
  UserNameField := DS.FieldByName('USERNAME');

  while not DS.Eof do
  begin
    ShowMessage(UserNameField.AsString);
    DS.Next;
  end;

  // I'd probably remove the `Close` unless the function call
  // above specifically opened it before returning it.
  DS.Close;
end;
Run Code Online (Sandbox Code Playgroud)