0

大家好,对不起,如果这是重复的,但我的具体问题我还没有在任何地方看到答案。当我尝试在以下行中释放运行时创建的 ObjectList 时,出现“无效指针操作”:

  Prods := TItemProcedimento.Create(DM.FDQ).lerProdutos;
  Prods.DisposeOf; // <- Invalid Pointer Operation at 2nd iteration

所以,这是我的课程:

unit uItemProcedimento;

interface
[...]

type
  TItemProcedimento = class
[...]
public
    constructor Create(DataSet: TFDQuery);
    function lerProdutos: TObjectList<TItemProcedimento>;
[...]

constructor TItemProcedimento.Create(DataSet: TFDQuery);
begin
  FDataSet := DataSet;
end;

function TItemProcedimento.lerProdutos: TObjectList<TItemProcedimento>;
begin
  Result := TObjectList<TItemProcedimento>.Create;
  try
    FDataSet.Close;
    FDataSet.SQL.Clear;
    FDataSet.SQL.Add('SELECT *');
    FDataSet.SQL.Add('FROM Produto p');
    FDataSet.SQL.Add('JOIN ItensProcedimento IP on p.PRO_ID = IP.PRO_ID');
    FDataSet.SQL.Add('ORDER BY p.PRO_Nome');
    FDataSet.Open;
    while not FDataSet.Eof do
    begin
      PRO_ID := FDataSet.FieldByName('PRO_ID').AsInteger;
      PRO_Rendimento := FDataSet.FieldByName('PRO_Rendimento').AsInteger;
      PRO_Nome := FDataSet.FieldByName('PRO_Nome').AsString;
      PRO_Tipo := FDataSet.FieldByName('PRO_Tipo').AsInteger;
      PRO_Custo := FDataSet.FieldByName('PRO_Custo').AsFloat;
      PRO_Potencia := FDataSet.FieldByName('PRO_Potencia').AsFloat;
      IPR_Uso := FDataSet.FieldByName('IPR_Uso').AsFloat;
      Result.Add(self);
      FDataSet.Next;
    end;
  finally
    FDataSet.Close;
  end;

最奇怪的是我有另一个具有完全相同行为的类,并且该方法可以正常工作。是的,我正在创建对象并立即销毁它以测试我是否正确销毁它。在另一个类中,我有另一个具有相同代码的示例,但是这次它可以正常工作

 test := TMyClass.Create(DM.FDQ).lerTeste;
 test.DisposeOf;

为什么?我究竟做错了什么?这个测试代码在当前代码之前运行,也许它相关?

更新:通过应用 Remy Lebeau 建议的更改,我设法将项目正确添加到列表中并处理它们,以便代码的这个特定部分没有泄漏。但是在代码的另一部分中,我有一个 ObjectList 泄漏,我不知道如何修复。

在我的类中,我有一个属性是 TObjectList 属性,我有一个方法来检查列表是否已分配,如果没有,它会创建它并将其返回给调用列表的任何人。

[...]
type
  TProcedimento = class
  private
  [...]
    FPRC_Produtos: TObjectList<TItemProcedimento>;
  public
  [...]
  function getPRC_Produtos: TObjectList<TItemProcedimento>;
  function criaProcedimentos: TObjectList<TProcedimento>;
  [...]

function TProcedimento.GetPRC_Produtos: TObjectList<TItemProcedimento>;
begin
  if not Assigned(FPRC_Produtos) then
    FPRC_Produtos:= TObjectList<TItemProcedimento>.Create;
  result := FPRC_Produtos;
end;

function TProcedimento.criaProcedimentos: TObjectList<TProcedimento>;
var
  IPR: TItemProcedimento;
  Procedimento: TProcedimento;
  ds: TFDQuery;
begin
  result := TObjectList<TProcedimento>.Create;
  ds := TFDQuery.Create(nil);
  ds.Connection := FDataSet.Connection;
  IPR := TItemProcedimento.Create(ds);
  try
    FDataSet.Close;
    FDataSet.Open('SELECT * FROM Procedimento');
    while not FDataSet.Eof do
    begin
      Procedimento := TProcedimento.Create(FDataSet);
      Procedimento.PRC_ID := FDataSet.FieldByName('PRC_ID').AsInteger;
      Procedimento.PRC_Nome := FDataSet.FieldByName('PRC_Nome').AsString;
      Procedimento.PRC_Duracao := FDataSet.FieldByName('PRC_Duracao')
        .AsDateTime;
      Procedimento.PRC_Preco := FDataSet.FieldByName('PRC_Preco').AsCurrency;
      Procedimento.PRC_Custo := FDataSet.FieldByName('PRC_Custo').AsCurrency;
      Procedimento.PRC_Consumo := FDataSet.FieldByName('PRC_Consumo').AsFloat;
      Procedimento.FPRC_Produtos := IPR.getItensProcedimento(FPRC_ID);
      result.Add(Procedimento);
      FDataSet.Next;
    end;
  finally
    FDataSet.Close;
    IPR.DisposeOf;
    ds.DisposeOf;
  end;
end;

然后我在 for-in 循环中使用这个属性来提供一个包含我数据库中 procs 的列表

procedure TKBForm1.CarregaProcedimento;
var
  Procedimento: TProcedimento;
  Procs: TObjectList<TProcedimento>;
  [...]
begin
  Procs := TProcedimento.Create(DM.FDQ).criaProcedimentos;
  try
    LV_Procedimento.Items.Clear;
    LV_Procedimento.BeginUpdate;
    for Procedimento in Procs do
    begin
      with LV_Procedimento.Items.Add do
      [...]
  finally
    Procs.DisposeOf;
    Procedimento.GetPRC_Produtos.DisposeOf;
  end;
end;

但是这部分运行后仍然会发生泄漏:

73 - 88 bytes: TProcedimento x 1, TItemProcedimento x 2

我该如何解决?

4

0 回答 0