首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >返回TList时Delphi错误

返回TList时Delphi错误
EN

Stack Overflow用户
提问于 2017-08-25 00:58:29
回答 1查看 700关注 0票数 2

我提出了一个非常简单的申请,但我有一个问题,我真的不明白。请看下面的基本代码:

代码语言:javascript
复制
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。为什么我有无效的指针操作错误?

我真的无法理解,因为我正在正确地创建和销毁对象(我猜)。相反,这段代码工作得很好:

代码语言:javascript
复制
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相同的引用。我说的对吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-25 01:10:54

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

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

你一开始想做什么?以这种方式返回对象不是很好的做法。在1元素列表上调用Sort()也是没有意义的。

如果您试图随时间使用多个值填充test,则应该将test作为输入参数传递给testGenerics() (或者只允许testGenerics()通过Self直接访问test ),根本不要使用返回值。

无论如何,摆脱您的aList私有成员,因为您无论如何都不会对它做任何事情。

试试这个:

代码语言:javascript
复制
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.
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45872925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档