![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Утечка памяти [D6, Win2k, WinXP]
maxz © (2004-12-14 18:34:00)Hi2all!
В общем, у меня есть прога, в которой через определенные промежутки времени выполняется одна и та же процедура. после каждого такого выполнения теряется несколько килобайт оперативки. я полагаю, что неправильно работаю с указателями. подскажите, где ошибка?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls,Registry;
type
TRegPart=(rpLM, rpCU);
TAutorunType=(atRun,atRunOnce,atRunOnceEx,atRunServices,atRunServicesOnce);
PStartupRec = ^AStartupRec;
AStartupRec=record
name: string;
command: string;
loadedfrom: string;
end;
type
TForm1 = class(TForm)
Timer1: TTimer;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
procedure CheckRunData(rp: TRegPart;AType: TAutorunType;var d: TList);
end;
const
RUN='Software\Microsoft\Windows\CurrentVersion\Run';
RUN_ONCE='Software\Microsoft\Windows\CurrentVersion\RunOnce';
RUN_ONCE_EX='Software\Microsoft\Windows\CurrentVersion\RunOnceEx';
RUN_SERVICES='Software\Microsoft\Windows\CurrentVersion\RunServices';
RUN_SERVICES_ONCE='Software\Microsoft\Windows\CurrentVersion\RunServicesOnce';
var
Form1: TForm1;
implementation
procedure TForm1.CheckRunData(rp: TRegPart;AType: TAutorunType;var d: TList);
var
hReg: TRegIniFile;
i: integer;
RegName,RegPath: string;
val: TStringList;
sd: PStartupRec;
begin
i:=0;
val:=TStringList.Create;
hReg:=TRegIniFile.Create;
if rp=rpCU then RegName:='HKCU\' else RegName:='HKLM\';
case AType of
atRun: begin
RegName:=RegName+'Run';
RegPath:=RUN;
end;
atRunOnce: begin
RegName:=RegName+'RunOnce';
RegPath:=RUN_ONCE;
end;
atRunOnceEx: begin
RegName:=RegName+'RunOnceEx';
RegPath:=RUN_ONCE_EX;
end;
atRunServices: begin
RegName:=RegName+'RunServices';
RegPath:=RUN_SERVICES;
end;
atRunServicesOnce: begin
RegName:=RegName+'RunServicesOnce';
RegPath:=RUN_SERVICES_ONCE;
end;
end;
with hReg do begin
case rp of
rpLM: RootKey:=HKEY_LOCAL_MACHINE;
rpCU: RootKey:=HKEY_CURRENT_USER;
end;
OpenKey(RegPath,false);
GetValueNames(val);
CloseKey;
end;
for i:=0 to (val.Count-1) do begin
New(sd);
sd^.name:=val[i];
sd^.command:=hReg.ReadString(RegPath,val[i],'');
sd^.loadedfrom:=RegName;
d.Add(sd);
end;
val.Clear;
val.Free;
hReg.Free;
end;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
d: TList;
i: integer;
begin
d:=TList.Create;
for i:=0 to 10 do CheckRunData(rpCU,atRun,d);
for i:=0 to d.Count-1 do dispose(d[i]);
d.Free;
end;
end.
DiamondShark (2004-12-14 19:44:00) [1]
> Вот этот кусок можно существенно оптимизировать с помощью
> uses TypInfpo и массивов.
Оно и без uses неплохо получится:
const
RunConst = 'Software\Microsoft\Windows\CurrentVersion\';
Runs: array[TAutoRunType] of string = (
'Run',
'RunOnce',
'RunOnceEx',
'RunServices',
'RunServicesOnce');
...
RegPath := RunConst + Runs[AType];
Суслик (2004-12-14 19:18:00) [2]
> А можете объяснить
потому, что для типизированных указателей dispose сначала вызывает finalize, что приводит к очистке значений с управляемым временем жизни (например, длинные строки), а для нетипизированных dispose при компиляции заменяется на freemem, который просто освобождает кусок памяти, не заботясь о освобождении содержимого.
TUser (2004-12-14 19:10:00) [3]
> А вот так не теряется:
>
> for i:=0 to d.Count-1 do dispose(PStartupRec(d[i]));
А можете объяснить - почему, если сделать не через TList, а в виде связного списка, то никаких утечек не будет? А с TList'ом - действительно утечки. Например,
PMine = ^TMine;
TMine =
record
S1: string;
S2: string;
Next: PMine;
end;
var
Form1: TForm1;
implementation
const
C = 10000;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var p,po:PMine;
i:integer;
begin
po:=nil;
for i:=0 to C-1 do begin
New(p);
p^.Next:=po;
po:=p;
p^.S1:='ANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXT';
p^.S2:='ANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXTANY TEXT';
end;
showmessage('!');
while p <> nil do begin
po:=p^.Next;
Dispose(p);
p:=po;
end;
end;
TUser (2004-12-14 19:01:00) [4]1. Cоздание-уничтожение объектов надо писать в try..finally
2. Как часто выполняется эта процедура? Может ли быть такое, что очередное время Х наступит до того, как завершилась работа предыдущей итерации?
PS. Вот этот кусок можно существенно оптимизировать с помощью uses TypInfpo и массивов.
> case AType of
> atRun: begin
> RegName:=RegName+'Run';
> RegPath:=RUN;
> end;
> atRunOnce: begin
> RegName:=RegName+'RunOnce';
> RegPath:=RUN_ONCE;
> end;
> atRunOnceEx: begin
> RegName:=RegName+'RunOnceEx';
> RegPath:=RUN_ONCE_EX;
> end;
> atRunServices: begin
> RegName:=RegName+'RunServices';
> RegPath:=RUN_SERVICES;
> end;
> atRunServicesOnce: begin
> RegName:=RegName+'RunServicesOnce';
> RegPath:=RUN_SERVICES_ONCE;
> end;
> end;
DiamondShark (2004-12-14 18:48:00) [5]Вот здесь теряется:
> for i:=0 to d.Count-1 do dispose(d[i]);
А вот так не теряется:
for i:=0 to d.Count-1 do dispose(PStartupRec(d[i]));