返回TList时Delphi错误

时间:2017-08-25 00:58:29

标签: 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;

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.

基本上,当表单打开时,我将创建testaList,然后当我按下按钮时,将调用函数testGenerics。为什么我有无效指针操作错误?

我真的无法理解,因为我正在创建和销毁对象(我猜)。这段代码可以正常工作:

function TForm1.testGenerics: TList<integer>;
begin

  Result := TList<integer>.Create;
  Result.Add(4);

end;

在这种情况下,我将返回TList<integer>的实例,但在上面的情况下,我将返回aList的实例(这是一个TList)。

如果我在第一种情况下是正确的test := testGenerics就像test := aList(因为我实际上正在返回aList),所以我要给test提供与{aList相同的引用1}}。我对么?

1 个答案:

答案 0 :(得分:4)

在第一个示例中,每当您致电testGenerics()时,您都会重新指定test以指向aList对象。您正在丢失在test事件中创建的原始OnCreate对象的跟踪,因此它已被泄露。然后在OnDestroy事件中,当您调用test.Free时,它会崩溃,因为您事先已经释放了aList对象,因此您尝试再次释放同一个对象,这是无效的操作。

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

你首先要做的是什么?以这种方式返回物体并不是一种好的做法。在单元素列表上调用Sort()也没有意义。

如果您尝试使用多个值填充test,则应将test作为输入参数传递给testGenerics()(或者让testGenerics()访问{{ 1}}直接通过test),根本不要使用返回值。

无论如何,要摆脱你的Self私人会员,因为你无论如何都没有做任何事情。

试试这个:

aList