第1步: 使用代码编写应用程序:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Generics.Collections,
FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls;
type
TObjChild = class;
TObjTest = class
private
FName: string;
FChilds: TList<TObjChild>;
public
property Name: string read FName write FName;
property Childs: TList<TObjChild> read FChilds write FChilds;
constructor Create;
destructor Destroy; override;
end;
TObjChild = class
private
FAdress: string;
FPostalCode: string;
public
property Adress: string read FAdress write FAdress;
property PostalCode: string read FPostalCode write FPostalCode;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
{ TObjTeste }
constructor TObjTest.Create;
begin
FChilds := TObjectList<TObjChild>.Create;
end;
destructor TObjTest.Destroy;
var
i: integer;
begin
for i := 0 to FChilds.count -1 do
begin
FChilds[I].Free;
end;
FreeAndNil(FChilds);
inherited;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
ListObjs: TList<TObjTest>;
lObjTeste: TObjTest;
lObjChild: TObjChild;
J: Integer;
begin
ListObjs := TList<TObjTest>.Create;
for I := 0 to 5000 do
begin
lObjTeste := TObjTest.Create;
for J := 0 to 2000 do
begin
lObjChild := TObjChild.Create;
lObjTeste.FChilds.Add(lObjChild)
end;
ListObjs.Add(lObjTeste);
end;
if MessageDlg('Delete objects?', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbOK], 0) = idOK then
begin
for I := 0 To ListObjs.Count - 1
begin
ListObjs[I].Free;
end;
FreeAndNil(ListObjs);
end;
end;
end.
步骤2:运行应用程序并按下按钮1
按下确定按钮后,应用程序的消息dlg不释放内存
步骤3:重复步骤有时应用程序返回低内存
答案 0 :(得分:3)
问题在于:
constructor TObjTest.Create;
begin
FChilds := TObjectList<TObjChild>.Create;
end;
destructor TObjTest.Destroy;
var
i: integer;
begin
for i := 0 to FChilds.count - 1 do
begin
FChilds[i].Free;
end;
FreeAndNil(FChilds);
inherited;
end;
默认情况下,TObjectList<T>
取得其成员的所有权。所以你不需要,也不应该释放析构函数中的成员。
所以这里:
for i := 0 to FChilds.count - 1 do
begin
FChilds[i].Free;
end;
你释放会员。但接着在这里:
FreeAndNil(FChilds);
对象列表还释放成员。谁已经被释放了。双重免费会导致运行时错误。
修复方法是删除显式释放对象列表成员并依赖列表来完成工作:
destructor TObjTest.Destroy;
begin
FChilds.Free;
inherited;
end;
其成员的所有权是TObjectList<T>
存在的唯一原因。这是它提供的唯一功能,超出TList<T>
提供的功能。在此处阅读:http://docwiki.embarcadero.com/Libraries/en/System.Generics.Collections.TObjectList
最后,儿童的复数是儿童。