Delphi 处理添加到TStringList的对象

Delphi 处理添加到TStringList的对象,delphi,Delphi,我这样做对吗? 我正在用我在填充期间创建的记录填充TStringlist中的对象。 我已将TStringList.OwnsObjects设置为true。但是,当我关闭应用程序时,我会遇到访问冲突。下面是我的代码摘录 type PUsageData = ^TUsageData; TUsageData = record DeclaredIn: String; LineNumber: Integer; TotalUsage: Integer; end; ...

我这样做对吗?
我正在用我在填充期间创建的记录填充TStringlist中的对象。 我已将TStringList.OwnsObjects设置为true。但是,当我关闭应用程序时,我会遇到访问冲突。下面是我的代码摘录

type
  PUsageData = ^TUsageData;
  TUsageData = record
    DeclaredIn: String;
    LineNumber: Integer;
    TotalUsage: Integer;
  end;

...

var VarUsages: TStringList;    // object contains a TUsageData record


procedure BuildUsageList;
var idx, idy, n,m: Integer;
    sl: TStringList;
    s,t: String;
    rec: PUsageData;
begin
  VarUsages.Clear;
  sl:= TStringList.Create;
  s := '';
  // First make a list and create a record for each variable declared in program
  for idx := 0 to IncludeList.Count -1 do begin
    GetSource(IncludeList[idx], sl);
    for idy := 0 to sl.Count -1 do begin
      t := '';
      t := CodeAnalyser.GetItems(sl[idy], caVariables);
      if t > '' then begin
        system.New(Rec);
        rec.DeclaredIn := IncludeList[idx];
        rec.LineNumber := idy;
        rec.TotalUsage := 0;
        VarUsages.AddObject(t, TObject(rec));
      end;
    end;
  end;
end;

...

initialization
  VarUsages := TStringList.Create;
  VarUsages.OwnsObjects := true;

finalization
  VarUsages.Free;
end.
我使用的是Delphi10.1


我还想知道当我清除StringList时会发生什么。它是否处理对象?

您至少有三种方法来处理此问题:

1.手动处理记录 因为您存储的是指向记录的指针,而不是
TObject
子体,所以不能依赖
OwnsObjects
。将其设置为
False

释放
TStringList
之前,您应该手动
处理每个记录:

for I := 0 to VarUsages.Count - 1 do
  Dispose(PUsageData(VarUsages.Objects[i]));
请注意,转换为
PUsageData
对于
Dispose
正常工作非常重要

由于您将
OwnsObjects
设置为
False
,因此字符串列表不会尝试释放“对象”,因此您可以立即调用:

VarUsages.Free;
请注意,
Dispose
将负责正确完成记录,包括其中的字符串

注意:正如David Heffernan评论的那样:不要忘记,除了在销毁字符串列表时手动处理外,无论何时删除或修改项目,都必须这样做。在国际海事组织看来,这使得其他两种选择更具吸引力

2.使用对象(类实例)而不是记录 或者,您可以将
TUsageData
转换为一个简单的类(没有方法,没有属性,只有公共字段):

然后可以将
OwnsObjects
设置为
True
,并让字符串列表负责释放它们。这种情况也适用于ARC管理的目标。使用
Rec:=TUsageData.Create,而不是
New
。据我所知,您可以使用相同的代码

3.不使用TStringList 使用类似于
t列表
,而不是字符串列表,其中
t图像数据
可以保留为记录。不需要使用指针。只需将
t
字符串也放入记录中。由于您正在处理记录,因此不需要释放任何内容,当然
TList
本身除外。释放它也会完成其中的记录

  Rec: TUsageData; // record!
  ...
  t := CodeAnalyser.GetItems(sl[idy], caVariables);
  if t > '' then 
  begin
    Rec.t := t;
    Rec.DeclaredIn := IncludeList[idx];
    Rec.LineNumber := idy;
    Rec.TotalUsage := 0;
    VarUsages.Add(Rec);

您使用的是记录,而不是对象,此处显示的代码不会处理记录(您不能让记录充当
TObject
)。为什么不使用简单类?指针不是对象。无论如何,你用错了类。将字符串放入记录中,并使用
TListAs以及在销毁集合时手动处理,无论何时删除或修改item@David:的确如此。我要补充一点。
  Rec: TUsageData; // record!
  ...
  t := CodeAnalyser.GetItems(sl[idy], caVariables);
  if t > '' then 
  begin
    Rec.t := t;
    Rec.DeclaredIn := IncludeList[idx];
    Rec.LineNumber := idy;
    Rec.TotalUsage := 0;
    VarUsages.Add(Rec);