有关内存释放问题(200分)

  • 主题发起人 主题发起人 xiakaijun
  • 开始时间 开始时间
X

xiakaijun

Unregistered / Unconfirmed
GUEST, unregistred user!
我的程序需大量的数学运算,当执行一定时间后,就会出现‘系统虚拟内存不足’,不能再运行。我的机器是32M内存,硬盘4.3G,虚拟内存放的较大,我检查了程序,该释放内存的地方我都释放了,但问题一直不能解决,现将部分程序代码copy如下,请诸位赐教(请在您的环境中运行一下,我想让下面的代码运行起来并不难,)(我用的是Delphi5)

请看内存释放正确否,在这里算法并不重要
///////////////////////////////原代码

////////////////////////////////////////////////////main
unit main;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls,structData,complexclass,Inifiles;

type
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
Button2: TButton;
Bevel1: TBevel;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
Label6: TLabel;
Label7: TLabel;
Edit6: TEdit;
Label8: TLabel;
Animate1: TAnimate;
Button3: TButton;
procedure Button1Click(Sender: TObject;ii:integer);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation

uses cdbam;

{$R *.DFM}

function Checktheresult(temp1, temp2: T1Dcomplex): boolean;
var
i:byte;
begin
result:=true;
for i:=low(temp1) to high(temp2) do
begin
if (abs(temp1.a-temp2.a)>zero) or (abs(temp1.b-temp2.b)>zero) then
begin
result:=False;
exit;
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject;ii:integer);
var
acdbam:TCdbam;
i,j:byte;
tempx :T1DComplex;
yesorno:boolean;
Localcount:byte;
Globalcount:byte;
myinifile:Tinifile;
str:string;
begin

Globalcount:=0;
for i:=0 to strtoint(edit5.text)-1 do
begin
Application.ProcessMessages;
localcount:=0;
acdbam:=TCdbam.create(ii,strtoint(edit2.text),strtoint(edit3.text),strtoint(edit4.text));
SetLength(tempx ,acdbam.weishuX);
for j:=0 to acdbam.ybduishu-1 do
begin

acdbam.Execute(j);
yesorno:=Checktheresult(acdbam.Finputy,acdbam.Y[j]);
if yesorno then
localcount:=localcount+1
else
break;
end;
if localcount>=acdbam.ybduishu then
Globalcount:=Globalcount+1;
acdbam.destory;
end;
label6.caption:=inttostr(ii)+' : '+inttostr(Globalcount);
str:=ExtractFilepath(Application.ExeName);
str:=str+'cdbam.ini';
myinifile:=TiniFile.create(str);
myinifile.writeInteger('CDBAM的样本对数与回忆样本X='+form1.edit2.text+'维','样本X的维数',strtoint(Form1.edit2.text));
myinifile.writeInteger('CDBAM的样本对数与回忆样本X='+form1.edit2.text+'维','样本Y的维数',strtoint(Form1.edit3.text));
myinifile.writeInteger('CDBAM的样本对数与回忆样本X='+form1.edit2.text+'维','分割数q',strtoint(Form1.edit4.text));
myinifile.WriteInteger('CDBAM的样本对数与回忆样本X='+form1.edit2.text+'维',inttostr(ii)+'对样本',Globalcount);

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
k:integer;
begin
Animate1.Visible:=True;
Animate1.active:=True;
for k:=strtoint(edit1.text) to strtoint(edit6.text) do
begin

Application.ProcessMessages;
button1click(self,k);//{button1在form1上已被我delete,在这里 仅作一过程用}
end;
Animate1.Active:=false;
Animate1.Visible:=False;
end;

end.

///////////////////////////////////define some struct or array

unit structData;

interface
uses SysUtils, Classes,complexclass;

Type
T1DComplex = array of TComplex;
T2DComplex = array of T1DComplex;
implementation

end.
//本程序所有变量说明:
{ X : 输入的总体样本,
Y : 输入的总体样本,
ybduishu : 样本总对数,
weishuX : X类的样本维数,
weishuY : X类的样本维数,
quan : weishux*weishuY维的权矩阵
Q : 复平面单位圆的等分数,即:数据集合中的数据数,
ComplexClass : 复数类的所有用法定义
CDBAM : 复数域BAM类
}
///////////////////////////////////////////////////////////////{
define a cdbam class 所有的运都在这里,请看释放内存是否正确,我用了多种方法freeandnil destroy free.....
////////////////////////////}

unit cdbam;

interface
uses math,structData,complexclass,Sysutils;

Type
TCdbam = class
private
Fybduishu : byte;
FweishuX : byte;
FweishuY : byte;
Fq : byte;
FX : T2DComplex;
FY : T2DComplex;
Fquan : T2DComplex;
FinputX : T1DComplex;

public
FinputY : T1DComplex;
protected
procedure SetX(value:T2DComplex);
procedure SetY(value:T2DComplex);
procedure RandProdureX;
procedure RandProdureY;
procedure Computequan;
function UpdateRule(value,tp:TComplex):TComplex
//@(Z)=exp(j2PIv/q),if ..... else previous state;
function CompareArray(first,second:T1DComplex):boolean;
public
constructor create(ybshu:byte;weix:byte;weiy:byte;qfen:byte);virtual;
destructor destory;virtual;
procedure Execute(jj:byte);
procedure SetsomeparamZero;
property ybduishu : byte
read Fybduishu
property weishuX :byte
read Fweishux
property weishuY :byte
read Fweishuy
property Q :byte
read FQ
property X:T2DComplex
read FX
property Y:T2DComplex
read FY
property quan : T2DComplex
read Fquan

end;



implementation

{ TCdbam }

function TCdbam.CompareArray(first, second: T1DComplex): boolean;
var
i:byte;
begin
result:=true;
for i:=low(first) to high(first) do
begin
if not ComplexCompare(First,Second) then
begin
result:=false;
exit;
end;
end;

end;

procedure TCdbam.Computequan;
var
i,j,k:byte;
temp,temp1:TComplex;
begin
SetLength(Fquan ,FweishuX,FweishuY );
temp:=TComplex.create;
Temp1:=TComplex.create;
for i:=0 to FWeishux-1 do
for j:=0 to Fweishuy-1 do
begin
for k:=0 to Fybduishu-1 do
begin
temp1:=complexMul(ComplexConjugate(FX[k]),FY[k][j]);
temp :=complexAdd(temp,temp1);
end;
Fquan[j]:=TComplex.create;
ComplexFuzhi(Fquan[j],temp);
if abs(Fquan[j].a)<zero2 then
Fquan[j].a:=0;
if abs(Fquan[j].b)<zero2 then
Fquan[j].b:=0;
temp.SetZero;
temp1.SetZero;
end;
FreeAndNil(temp);
FreeAndNil(temp1);

end;

constructor TCdbam.create(ybshu, weix, weiy, qfen: byte);
var
i:byte;
begin
Fybduishu:=ybshu;
Fweishux:=weix;
Fweishuy:=weiy;
Fq:=qfen;
RandProdureX;
RandProdureY;
Computequan;
setlength(FInputY,weiy);
for i:=low(FInputY) to high(FInputY) do
FInputY:=TComplex.create;
end;

destructor TCdbam.destory;
var
i,j:integer;
begin
inherited;
for i:=0 to high(Fx) do
for j:=low(FX) to high(FX) do
begin
// FX[j].free;
//FX[j]:=nil;
FX[j].destroy;
FX[j]:=nil;
end;
for i:=low(FY) to high(Fy) do
for j:=low(Fy) to high(FY) do
begin
// Fy[j].free;
// FY[j]:=nil;
FY[j].destroy;
FY[j]:=nil;
end;


for i:=low(FInputX) to high(FInputX) do
begin
freeandnil(FInputX);

end;
for i:=low(FinputY) to high(FinputY) do
begin
FinputY.destroy;
Finputy:=nil;
end;

for i:=low(Fquan) to high(Fquan) do
for j:=low(Fquan) to high(Fquan) do
begin
Fquan[j].destroy;
Fquan[j]:=nil;
end;


end;

procedure TCdbam.Execute(jj:byte);
var
i,j:byte;
temp1,temp2:TComplex;
tx,ty:T1DComplex;
begin
Setlength(FInputx,Fweishux);
for i:=low(FInputX) to high(FinputX) do
begin
FinputX:=TComplex.create;
ComplexFuzhi(Finputx,FX[jj]);
end;
temp2:=TComplex.create;
SetLength(tX,Fweishux);
SetLength(tY,FweishuY);
////////////////////////////////////////////////////////////
{ should in your program first input something to inputx or inputy}

///////////////////////////////////////////////////////////
for i:=0 to FweishuX-1 do
begin
tx:=TComplex.create;
ComplexFuzhi(tx,Finputx);
end;
for j:=0 to FweishuY-1 do
begin
tY[j]:=TComplex.create;
ComplexFuzhi(tY[j],FInputY[j]);
end;
while(1=1) do
begin
for i:=0 to Fweishuy-1 do //Y'=@(xs)
begin
for j:=0 to FweishuX-1 do
begin
temp1:=ComplexMul(FInputX[j],FQuan[j]);
temp2:=ComplexAdd(temp2,temp1);
end;
FinputY:=UpdateRule(temp2,ty);
temp2.SetZero;
end;
for i:=0 to FWeishuX-1 do
begin
for j:=0 to FweishuY-1 do
begin
temp1:=ComplexMul(FinputY[j],ComplexConjugate(FQuan[j]));
temp2:=complexAdd(temp2,temp1);
end;
FinputX:=UpdateRule(temp2,tX);
temp2.SetZero;
end;
if CompareArray(tX,Finputx) and CompareArray(tY,Finputy) then
break
else
begin
for i:=0 to FweishuX-1 do
ComplexFuzhi(tX,Finputx);
for j:=0 to FweishuY-1 do
ComplexFuzhi(tY[j],FinputY[j]);
end;
end;
for i:=low(tx) to high(tx) do
begin
// freeandnil(tx);
//freeandnil(Finputx);
tx.destroy;
tx:=nil;
Finputx.destroy;
Finputx:=nil;

end;
for i:=low(ty) to high(ty) do
begin
//freeandnil(ty);
ty.destroy;
ty:=nil;
end;

end;

procedure TCdbam.RandProdureX;
var
i,j:byte;
v:byte;
r,arg:double;
begin
SetLength(FX,Fybduishu,FweishuX );
Randomize;
for i:=0 to Fybduishu-1 do
for j:=0 to Fweishux-1 do
begin
FX[j]:=TComplex.create;
v:=Random(Fq);
r:=1;
arg:=2*PI*v/FQ;
FX[j].a:=r*cos(arg);
FX[j].b:=r*sin(arg);
if abs(FX[j].a)<Zero1 then
FX[j].a:=0;
if abs(FX[j].b)<zero1 then
FX[j].b:=0;
end;
end;

procedure TCdbam.RandProdureY;
var
i,j:byte;
v:byte;
r,arg:double;
begin
SetLength(FY,Fybduishu,FweishuY );
Randomize;
for i:=0 to Fybduishu-1 do
for j:=0 to FweishuY-1 do
begin
FY[j]:=TComplex.create;
v:=Random(Fq);
r:=1;
arg:=2*PI*v/FQ;
FY[j].a:=r*cos(arg);
FY[j].b:=r*sin(arg);
if abs(FY[j].a)<Zero1 then
FY[j].a:=0;
if abs(FY[j].b)<zero1 then
FY[j].b:=0;
end;

end;

procedure TCdbam.SetsomeparamZero;
var
i,j:byte;
begin
for i:=low(Finputx) to high(Finputx) do
begin
Finputx.SetZero;
end;
for j:=low(Finputy) to high(Finputy) do
begin
Finputy[j].SetZero;
end;

end;

procedure TCdbam.SetX(value: T2DComplex);
begin
FX:=value;
end;

procedure TCdbam.SetY(value: T2DComplex);
begin
FY:=value;
end;

function TCdbam.UpdateRule(value, tp: TComplex): TComplex;
var
v:byte;
temp:TComplex;
arg,r:double;
begin
temp:=TComplex.create;
if( abs(value.a)<Zero1 ) and (abs(value.b)<zero1) then
begin
temp.a:=tp.a;
temp.b:=tp.b;
end
else
begin
r:=sqrt(sqr(value.a)+sqr(value.b));
arg:=arccos(value.a/r);
if value.b<0 then
arg:=2*PI-arg;
v:=trunc((arg*Fq)/(2*PI)+0.5);

arg:=(2*PI*V)/Fq;
temp.a:=cos(arg);
temp.b:=sin(arg)
//givo 0 if abs(temp.b)<zero
if abs(temp.a)<zero1 then
temp.a:=0;
if abs(temp.b)<zero1 then
temp.b:=0;
end;
result:=temp;

end;

end.
//////////////////////// define a complex class


unit ComplexClass;

interface
uses
math,SysUtils, Classes;
const
Zero=0.0000001
//小数点后9位时,差:
zero1=0.0000001;
zero2=0.000000000001;
PI=3.14159262526;
Type
TComplex = class
private
Fa:double;
Fb:double;

protected
procedure Seta(value:double);
procedure Setb(value:double);

public
constructor create;overload;
constructor create(a,b:double);overload;
constructor create(temp:TComplex);overload;
destructor destory;overload;
function Getunitcomplex(value:TComplex):TComplex;
procedure SetZero;
property a:double
read Fa write Seta;
property b:double
read Fb write setb;

// procedure covertabtorarg;
// procedure covertrargtoab;
end;
Function complexAdd(x,y:Tcomplex):TComplex;
Function complexSbu(x,y:Tcomplex):TComplex;
Function complexMul(x,y:TComplex):TComplex
overload;
Function ComplexMul(x:double;y:TComplex):TComplex;overload;
Function ComplexConjugate(value:Tcomplex):TComplex;
Function ComplexCompare(first,second:Tcomplex):boolean;
Function ComplexUnitValue(value:Tcomplex):TComplex;
procedure ComplexFuzhi(first,second:Tcomplex);
implementation

{ TComplex }
Function ComplexUnitValue(value:TComplex):TComplex;
var
temp:TComplex;
begin
temp:=TComplex.create;
temp.a:=value.a/sqrt(sqr(value.a)+sqr(value.b));
temp.b:=value.b/sqrt(sqr(value.a)+sqr(value.b));
result:=temp;
end;
procedure ComplexFuzhi(first,second:Tcomplex);
begin
first.a:=second.a;
first.b:=second.b;

end;

Function ComplexCompare(first,second:TComplex):boolean;
begin
if (abs(first.a-second.a)<zero) and (abs(first.b-second.b)<zero) then
result:=true
else result:=false;
end;
Function ComplexConjugate(value:TComplex):TComplex;
var
temp:TComplex;
begin
temp:=TComplex.create;
temp.a:=value.a;
temp.b:=(-1)*value.b;

result:=temp;
end;
Function complexAdd(x,y:Tcomplex):TComplex;
var
temp:Tcomplex;
begin
temp:=TComplex.create;
temp.a:=x.a+y.a;
temp.b:=x.b+y.b;

result:=temp;
end;
Function complexSbu(x,y:Tcomplex):TComplex;
var
temp:Tcomplex;
begin
temp:=TComplex.create;
temp.a:=x.a-y.a;
temp.b:=x.b-y.b;

result:=temp;
end;
Function complexMul(x,y:Tcomplex):TComplex;overload;
var
temp:TComplex;
begin
temp:=TComplex.create;
temp.a:=x.a*y.a-x.b*y.b;
temp.b:=x.a*y.b+x.b*y.a;

result:=temp;
end;

Function complexMul(x:double;y:Tcomplex):TComplex;overload;
var
temp:TComplex;
begin
temp:=TComplex.create;
temp.a:=x*y.a
temp.b:=x*y.b;

result:=temp;
end;

constructor TComplex.create(a, b: double);
begin

Fa:=a;
Fb:=b;
end;

constructor TComplex.create(temp: TComplex);
begin
Fa:=temp.a;
Fb:=temp.b;
end;

constructor TComplex.create;
begin
Fa:=0;
Fb:=0;
end;

destructor TComplex.destory;
begin
free;
end;

function TComplex.Getunitcomplex(value: TComplex): TComplex;
var
temp:TComplex;
begin
temp:=TComplex.create;
temp.a:=value.a/(sqrt(sqr(value.a)+sqr(value.b)));
temp.b:=value.b/(sqrt(sqr(value.b)+sqr(value.b)));

result:=temp;
end;

procedure TComplex.Seta(value: double);
begin
Fa:=value;
end;



procedure TComplex.Setb(value: double);
begin
Fb:=value;
end;



procedure TComplex.SetZero
begin
Fa:=0;
Fb:=0;
end;

end.

////////////////////////////////////main form


object Form1: TForm1
Left = 188
Top = 115
Width = 549
Height = 375
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object PageControl1: TPageControl
Left = 0
Top = 0
Width = 537
Height = 345
ActivePage = TabSheet1
TabOrder = 0
object TabSheet1: TTabSheet
Caption = 'CDBAM'
object Bevel1: TBevel
Left = 144
Top = 48
Width = 225
Height = 177
end
object Label1: TLabel
Left = 160
Top = 64
Width = 48
Height = 13
Caption = '样本对数'
end
object Label2: TLabel
Left = 160
Top = 96
Width = 55
Height = 13
Caption = '样本X维数'
end
object Label3: TLabel
Left = 160
Top = 128
Width = 55
Height = 13
Caption = '样本Y维数'
end
object Label4: TLabel
Left = 160
Top = 160
Width = 60
Height = 13
Caption = '随机分割数'
end
object Label5: TLabel
Left = 160
Top = 192
Width = 48
Height = 13
Caption = '测试次数'
end
object Label6: TLabel
Left = 432
Top = 152
Width = 36
Height = 13
Caption = '回忆率'
end
object Label7: TLabel
Left = 296
Top = 64
Width = 9
Height = 13
Caption = 'to'
end
object Label8: TLabel
Left = 232
Top = 64
Width = 23
Height = 13
Caption = 'From'
end
object Button2: TButton
Left = 272
Top = 256
Width = 89
Height = 25
Caption = '&amp;Close'
TabOrder = 0
OnClick = Button2Click
end
object Edit1: TEdit
Left = 264
Top = 64
Width = 25
Height = 21
TabOrder = 1
Text = '1'
end
object Edit2: TEdit
Left = 232
Top = 96
Width = 121
Height = 21
TabOrder = 2
Text = '10'
end
object Edit3: TEdit
Left = 232
Top = 128
Width = 121
Height = 21
TabOrder = 3
Text = '10'
end
object Edit4: TEdit
Left = 232
Top = 160
Width = 121
Height = 21
TabOrder = 4
Text = '4'
end
object Edit5: TEdit
Left = 232
Top = 192
Width = 121
Height = 21
TabOrder = 5
Text = '100'
end
object Edit6: TEdit
Left = 312
Top = 64
Width = 41
Height = 21
TabOrder = 6
Text = '10'
end
object Animate1: TAnimate
Left = 408
Top = 40
Width = 80
Height = 50
Active = False
CommonAVI = aviFindFolder
StopFrame = 29
Visible = False
end
object Button3: TButton
Left = 168
Top = 256
Width = 75
Height = 25
Caption = '开始多次测试'
TabOrder = 8
OnClick = Button3Click
end
end
object TabSheet2: TTabSheet
Caption = 'ICDBAM'
ImageIndex = 1
end
end
end

 
问题应该出在下面几个函数:
function TCdbam.UpdateRule(value, tp: TComplex): TComplex;
Function ComplexUnitValue(value:TComplex):TComplex;
Function complexAdd(x,y:Tcomplex):TComplex;
Function ComplexConjugate(value:TComplex):TComplex;
Function complexSbu(x,y:Tcomplex):TComplex;
Function complexMul(x,y:Tcomplex):TComplex;
Function complexMul(x:double;y:Tcomplex):TComplex;
每次调用均生成了一个TComplex实例,分配了内存。而你在调用后没有释放。
在:
procedure TCdbam.Computequan;
等过程中的Temp, Temp1实例化了,因为你给它赋的就是一个有上面这些函数生成
的。


 
告诉你一个最基本的原则,就是,你只要自己create过的,
都要在不用的地方把它free掉, 注意不要丢失。
 
他们说的对,你主要是用destroy代替free了. 看看delphi关于destroy的帮助:
<b>Do not</b> call Destroy directly in an application. Instead, call Free.
Free verifies that the control is not already freed, and only then
calls Destroy.

Applications should only free controls explicitly when the Create
method was called to create an instance of the control without giving
it an owner.
 
尽量不要用destroy,应该多用free,因为free比destroy要安全的多。
 
诸位,其实我也不是不知道free 和 destroy 的差别,也用过free,但效果并不明显,我在NT下用任务管理器观察程序运行时的内存使用和释放情况,但总看不到内存被明显释放。
 
把tcomplex等等类声明为 class(tobject)吧,
这样会好很多,尤其是你调用的freeandnil(...),
Delphi中明确写着不要对非tobject子类调用此过程。
 
温大侠:不写TObject的就是从TObject继承的类。
所以FreeAndNil可以用于任何对象,文档的意思是不要传入普通变量。

建议你装BoundsChecker for Delphi,内存泄漏可以很容易的检查出来。
 
FREE 检查 指针是否为空,然后 释放
DESTORY 不检查,所以比较危险。
 
楼在各位大虾的方法如果都没有明显效果的话,
我想你再从这个角度来看看:
  你的硬盘只有4.3G,不知道你分了几个区?
  是不是Window所指定的虚拟目录所在分区的空间不够了?
 
我拜读了一下你的程序,觉得该释放的地方都释放了。{除了TComplex实例}
首先,此问题我认为和用destory或free无关,如果用destory,又恰好指针为nil,一定会出现
delphi自带异常提示.
其次,即使有tcomplex实例没有释放,冲其量不过寥寥。不会大到出现如此提示。
因此,我觉得这不是程序的问题,也许的确和清风大侠所说有关。
 
同意Hexi,解决:
把这些function改写为procedure,返回值作为一个参数传入;
并在使用这些过程前创建,使用后立即销毁。
 
是应该先从硬件角度考虑,设置一下虚拟内存、整理磁盘,虽然很低级,但往往会很有效的!
 
两种可能性都存在

第一是你的程序确实需要很多内存空间, 很可能运行当中出现内存不足的情况. 第二个可能是
你的程序中有泄漏. 看你后面的那段计算代码, 动态生成了很多东西, 这段程序很可存在内存
泄漏:
procedure TCdbam.Computequan;
var
i,j,k:byte;
temp,temp1:TComplex;
begin
SetLength(Fquan ,FweishuX,FweishuY );
temp:=TComplex.create;
Temp1:=TComplex.create;
for i:=0 to FWeishux-1 do
for j:=0 to Fweishuy-1 do
begin
for k:=0 to Fybduishu-1 do
begin
temp1:=complexMul(ComplexConjugate(FX[k]),FY[k][j]);
temp :=complexAdd(temp,temp1);
end;
Fquan[j]:=TComplex.create;
ComplexFuzhi(Fquan[j],temp);
if abs(Fquan[j].a)

还不知道着两个函数 ComplexMul,ComplexAdd中是否创建了任何对象, 希望里面没有创建.
作为Object的函数调用 temp :=complexAdd(temp,temp1)
这种调用不是很可靠, 不应该
像使用一般变量或者纪录那样使用Object. 因为入口对象Temp与返回对象Temp其实是一个
对象. 对象作为函数的参数是通过指针操作的.

后面的两语句也不可靠
Fquan[j]:=TComplex.create;
ComplexFuzhi(Fquan[j],temp);
为什么不用 Fquan[j] := temp 而去在去创建一个对象然后复制temp呢

在程序中动态创建的对象,最好用 try....finally...end 结构, 例如:

Procedure MyProcedure;
var
List1, List2: TStringList;
begin
List1 := TStringList.Create;
try
...;
List2 := TStringList.Create;
try
...;
finally
List2.free;
end;
finally
List1.free;
end;
end;
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
529
import
I
I
回复
0
查看
671
import
I
后退
顶部