返回TList时出现Delphi错误

返回TList时出现Delphi错误,delphi,Delphi,我已经做了一个非常简单的应用程序,但我有一个问题,我真的无法理解。看看这个基本代码: unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, generics.collections, Vcl.StdCtrls; ty

我已经做了一个非常简单的应用程序,但我有一个问题,我真的无法理解。看看这个基本代码:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, generics.collections, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    test: TList<integer>;
    aList: TList<integer>;
  public
    { Public declarations }
    function testGenerics: TList<integer>;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 test := testGenerics;
 test.Sort;
 showmessage(test[0].tostring);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 test := TList<integer>.Create;
 aList := TList<integer>.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 aList.Free;
 test.Free;
end;

function TForm1.testGenerics: TList<integer>;
begin

  aList.Add(4);
  result := aList;

end;

end.
在本例中,我将返回一个TList实例,但在上述情况下,我将返回一个TList实例


如果我在第一个案例中是正确的,test:=testGenerics类似于test:=aList,因为我实际上返回了aList,所以我将为test提供与aList相同的引用。我说得对吗

在第一个示例中,无论何时调用testGenerics,都将测试重新分配给指向aList对象的点。您正在失去在OnCreate事件中创建的原始测试对象的跟踪,因此它被泄漏。然后在OnDestroy事件中,当您调用test.Free时,它会崩溃,因为您事先已经释放了aList对象,所以您正在尝试第二次释放同一对象,这是一个无效的操作

在第二个示例中,您仍在泄漏原始测试对象和分配给测试的每个TList(最后一个除外),但您不再将测试重新分配给aList对象,因此OnDestroy事件中没有崩溃,因为两个变量都指向不同的对象

你首先想完成什么?以这种方式返回对象不是好的做法。在单元素列表上调用Sort也没有意义

如果您试图在一段时间内用多个值填充测试,那么您应该将测试作为输入参数传递给testGenerics,或者让testGenerics直接通过Self访问测试,根本不使用返回值

在任何情况下,摆脱你的私人成员,因为你没有做任何事情与它无论如何

试试这个:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, generics.collections, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    test: TList<integer>;
  public
    { Public declarations }
    procedure testGenerics(aList: TList<integer>);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  testGenerics(test);
  test.Sort;
  ShowMessage(test[0].tostring);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  test := TList<integer>.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  test.Free;
end;

procedure TForm1.testGenerics(aList: TList<integer>);
begin
  // FYI, a better way to exercise Sort()
  // would be to use RandomRange() instead
  // of a hard-coded number...
  aList.Add(4);
end;

end.

谢谢你,雷米!为了修复漏洞,我应该使用第二个示例,并删除在FormCreate中创建测试?那么,ondestroy中的test.free就可以了,因为我的UndeStoods只会在您第一次调用testGenerics时防止泄漏,但在后续调用时仍然会泄漏,因为您在调用testGenerics之前没有调用test.free。
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, generics.collections, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    test: TList<integer>;
  public
    { Public declarations }
    procedure testGenerics(aList: TList<integer>);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  testGenerics(test);
  test.Sort;
  ShowMessage(test[0].tostring);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  test := TList<integer>.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  test.Free;
end;

procedure TForm1.testGenerics(aList: TList<integer>);
begin
  // FYI, a better way to exercise Sort()
  // would be to use RandomRange() instead
  // of a hard-coded number...
  aList.Add(4);
end;

end.