Я сделал упрощенный пример, который моделирует мою проблему. Вот две процедуры, которые реагируют на кнопки на форме.
Как Вы легко поймете, первая, с каждым новым кликом, создает массив строк, которым присваивает различную длину.
Вторая должна почистить память.
Но в результате, если нажимать по такой схеме:
12
112
1112
11112
и т.д., т.е. 1-ю кнопку нажимать все больше раз, то происходит все большая утечка памяти примерно по 4-8 Kb.
Расскажите, пожалуйста в чем дело?!?!?!?
type
ptry1=^ttry1;
ttry1=array[1..4096] of string;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
t : array of ptry1;
{ Public declarations }
end;
procedure TForm1.Button1Click(Sender: TObject);
var
p : ptry1;
i : longint;
s : String;
begin
new(p);
for i:=1 to 4096 do
Begin
setlength(s,i);
p^[i] := s;
setlength(s,0);
End;
i := length(t);
setlength(t, i+1);
t[i] := p;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i,j: longint;
begin
for i := 0 to length(t)-1 do
Begin
for j := 1 to 4096 do
setlength(t[i]^[j],0);
dispose(t[i]);
End;
t:=nil;
end;
там реальный код сложнее. Этот — просто макет, который производит ту же утечку, что и реальная прога.
Я знаю, что если в первой процедуре на использовать s, а сразу устанавливать длину для элементов массива, то утечки нету. Так в чем проблема? кто знает?
Re: Люди!!! Ткните мне, пожалуйста, пальцем в утечку!!
Здравствуйте Иван Ходов, Вы писали:
ИХ>Я сделал упрощенный пример, который моделирует мою проблему. Вот две процедуры, которые реагируют на кнопки на форме. ИХ>Как Вы легко поймете, первая, с каждым новым кликом, создает массив строк, которым присваивает различную длину. ИХ>Вторая должна почистить память. ИХ>Но в результате, если нажимать по такой схеме: ИХ>12 ИХ>112 ИХ>1112 ИХ>11112 ИХ>и т.д., т.е. 1-ю кнопку нажимать все больше раз, то происходит все большая утечка памяти примерно по 4-8 Kb.
ИХ>Расскажите, пожалуйста в чем дело?!?!?!?
ИХ>type ИХ> ptry1=^ttry1; ИХ> ttry1=array[1..4096] of string;
ИХ>TForm1 = class(TForm) ИХ> Button1: TButton; ИХ> Button2: TButton; ИХ> procedure Button1Click(Sender: TObject); ИХ> procedure Button2Click(Sender: TObject); ИХ> private ИХ> { Private declarations } ИХ> public ИХ> t : array of ptry1; ИХ> { Public declarations } ИХ> end;
ИХ>procedure TForm1.Button1Click(Sender: TObject); ИХ>var ИХ>p : ptry1; ИХ>i : longint; ИХ>s : String;
ИХ>begin ИХ>new(p); ИХ>for i:=1 to 4096 do ИХ> Begin ИХ> setlength(s,i); ИХ> p^[i] := s; ИХ> setlength(s,0); ИХ> End; ИХ>i := length(t); ИХ>setlength(t, i+1); ИХ>t[i] := p; ИХ>end;
ИХ>procedure TForm1.Button2Click(Sender: TObject); ИХ>var ИХ>i,j: longint; ИХ>begin ИХ>for i := 0 to length(t)-1 do ИХ> Begin ИХ> for j := 1 to 4096 do ИХ> setlength(t[i]^[j],0); ИХ> dispose(t[i]); ИХ> End; ИХ>t:=nil; ИХ>end;
ИХ>там реальный код сложнее. Этот — просто макет, который производит ту же утечку, что и реальная прога.
ИХ>Я знаю, что если в первой процедуре на использовать s, а сразу устанавливать длину для элементов массива, то утечки нету. Так в чем проблема? кто знает?
Может я и не прав, но мне кажется следующее. Если все есть так, как ты написал в самом конце пояснения, то у тебя при выходе из первой процедуры не вычищается кусок, ассоциированный с p ( new(p) ). Раз уж ты выделил его сам, то сам и зашибай!!!! ( delete(p) ). А то при выходе указатель созданный на стеке пришибается, а распределенная память не вычищается, ведь автосборщика "мусора" нет!
Безвыходных ситуаций не бывает, это просто такое состояние головного мозга!!!
Re: Люди!!! Ткните мне, пожалуйста, пальцем в утечку!!
Здравствуйте Иван Ходов, Вы писали:
ИХ>procedure TForm1.Button2Click(Sender: TObject); ИХ>var ИХ>i,j: longint; ИХ>begin ИХ>for i := 0 to length(t)-1 do ИХ> Begin ИХ> for j := 1 to 4096 do ИХ> setlength(t[i]^[j],0); ИХ> dispose(t[i]); ИХ> End;
SetLength(t, 0); ИХ>t:=nil; ИХ>end;
Может, поможет. Ты, кстати, как утечки определяешь?
Re[2]: Люди!!! Ткните мне, пожалуйста, пальцем в утечку!!
От:
Аноним
Дата:
12.04.02 00:13
Оценка:
Неплохо.
Гулял я тут по сайту — думал не плохие тут программеры — прочитал последние два ответа, мнение мое как-то сразу упало.
Ну так как? Не удалось выявить утечку? А то я могу своего друга попросить он может в отладчике посмотреть, как там все это на ассемблерном уровне, может он и выпадет(утечка). :)
Re[3]: Люди!!! Ткните мне, пожалуйста, пальцем в утечку!!
От:
Аноним
Дата:
12.04.02 02:41
Оценка:
Здравствуйте Аноним, Вы писали:
А>Неплохо. А>Гулял я тут по сайту — думал не плохие тут программеры — прочитал последние два ответа, мнение мое как-то сразу упало.
А>Ну так как? Не удалось выявить утечку? А то я могу своего друга попросить он может в отладчике посмотреть, как там все это на ассемблерном уровне, может он и выпадет(утечка). :)
Утечку я не нашел, но у меня отпала надобность. Мне никто че-то ничего путного не сказал ни здесь ни на "Мастерах Дельфи", так что я просто переделал алгоритм и переписал код.
Спасибо за предложение, но я не думаю, что твой друг согласится копаться в этом коде. Я сам знаю ассемблер достаточно хорошо, и точно знаю, что мне было бы лень искать утечку на Ассемблерном уровне. Просто в приведенном коде неправильно используется что-то из Дельфей, и я думал, что хоть кто-то из экспертов, посещающих RSDN или "Мастеров Дельфи" знает че не так.
Re[2]: Люди!!! Ткните мне, пожалуйста, пальцем в утечку!!
От:
Аноним
Дата:
12.04.02 02:46
Оценка:
Здравствуйте Yurik, Вы писали:
Y>Здравствуйте Иван Ходов, Вы писали:
ИХ>>procedure TForm1.Button2Click(Sender: TObject); ИХ>>var ИХ>>i,j: longint; ИХ>>begin ИХ>>for i := 0 to length(t)-1 do ИХ>> Begin ИХ>> for j := 1 to 4096 do ИХ>> setlength(t[i]^[j],0); ИХ>> dispose(t[i]); ИХ>> End; Y>SetLength(t, 0); ИХ>>t:=nil; ИХ>>end;
Нет. Не поможет. Это я даже не пробуя знаю.
X := nil;
и
SetLength(X, 0);
Это одна и та же операция и дублировать ее нет смысла.
Как я уже писал, если в первой процедуре не использовать S,
а присваивать значения сразу строкам в массиве, то утечки нету.
Y>Может, поможет. Ты, кстати, как утечки определяешь?
У меня есть MemProof, MemCheck, но эту утечку видно, даже в "Ctrl-Shift-Esc" :)
Re[2]: Люди!!! Ткните мне, пожалуйста, пальцем в утечку!!
От:
Аноним
Дата:
12.04.02 02:50
Оценка:
Здравствуйте AIR, Вы писали:
AIR>Может я и не прав, но мне кажется следующее. Если все есть так, как ты написал в самом конце пояснения, то у тебя при выходе из первой процедуры не вычищается кусок, ассоциированный с p ( new(p) ). Раз уж ты выделил его сам, то сам и зашибай!!!! ( delete(p) ). А то при выходе указатель созданный на стеке пришибается, а распределенная память не вычищается, ведь автосборщика "мусора" нет!
Вероятно, Вы ошибаетесь. Если я буду использовать delete(p) в первой процедуре, то не смогу обратиться к этой памяти во второй процедуре. А память вычищается строкой
dispose(t[i]);
Re: Люди!!! Ткните мне, пожалуйста, пальцем в утечку!!
От:
Аноним
Дата:
12.04.02 14:28
Оценка:
Здравствуйте Иван Ходов, Вы писали:
ИХ>Я сделал упрощенный пример, который моделирует мою проблему. Вот две процедуры, которые реагируют на кнопки на форме. ИХ>Как Вы легко поймете, первая, с каждым новым кликом, создает массив строк, которым присваивает различную длину. ИХ>Вторая должна почистить память. ИХ>Но в результате, если нажимать по такой схеме: ИХ>12 ИХ>112 ИХ>1112 ИХ>11112 ИХ>и т.д., т.е. 1-ю кнопку нажимать все больше раз, то происходит все большая утечка памяти примерно по 4-8 Kb.
ИХ>Расскажите, пожалуйста в чем дело?!?!?!?
ИХ>type ИХ> ptry1=^ttry1; ИХ> ttry1=array[1..4096] of string;
ИХ>TForm1 = class(TForm) ИХ> Button1: TButton; ИХ> Button2: TButton; ИХ> procedure Button1Click(Sender: TObject); ИХ> procedure Button2Click(Sender: TObject); ИХ> private ИХ> { Private declarations } ИХ> public ИХ> t : array of ptry1; ИХ> { Public declarations } ИХ> end;
ИХ>procedure TForm1.Button1Click(Sender: TObject); ИХ>var ИХ>p : ptry1; ИХ>i : longint; ИХ>s : String;
ИХ>begin ИХ>new(p); ИХ>for i:=1 to 4096 do ИХ> Begin ИХ> setlength(s,i); ИХ> p^[i] := s; ИХ> setlength(s,0); ИХ> End; ИХ>i := length(t); ИХ>setlength(t, i+1); ИХ>t[i] := p; ИХ>end;
ИХ>procedure TForm1.Button2Click(Sender: TObject); ИХ>var ИХ>i,j: longint; ИХ>begin ИХ>for i := 0 to length(t)-1 do ИХ> Begin ИХ> for j := 1 to 4096 do ИХ> setlength(t[i]^[j],0); ИХ> dispose(t[i]); ИХ> End; ИХ>t:=nil; ИХ>end;
ИХ>там реальный код сложнее. Этот — просто макет, который производит ту же утечку, что и реальная прога.
ИХ>Я знаю, что если в первой процедуре на использовать s, а сразу устанавливать длину для элементов массива, то утечки нету. Так в чем проблема? кто знает?
1.
Что такое t?
2. setlength(t[i]^[j],0); ??????????!!!!