![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Люди!!! Ткните мне, пожалуйста, пальцем в утечку памяти. [D5, Win2k, WinXP]
khodov © (2002-04-06 21:28:00)Я сделал упрощенный пример, который моделирует мою проблему. Вот две процедуры, которые реагируют на кнопки на форме.
Как Вы легко поймете, первая, с каждым новым кликом, создает массив строк, которым присваивает различную длину.
Вторая должна почистить память.
Но в результате, если нажимать по такой схеме:
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;
Fantasist (2002-04-07 09:17:00) [1]2khodov:
:)
Опс... Облом. А так хотелось кого-то поучить. Без наездов. :)
> Если ты не заметил, то перед тем, как освободить массив,
> я очищаю память, занятую каждой строкой в массиве.
Заметил. А потом забыл.
Попробую посмотреть по внимательнее.
А все-таки, а не пробывал ли ты то же самое сделать через PChar?
khodov (2002-04-07 07:55:00) [2]To MBo:
Я знаю, что 8 мег выделяется.
To Fanatist:
Спасибо за вводный курс лекций :). Я имею дело с Delphi начиная с 1-й версии и даже раньше :). За это время я успел изучить изменения, произошедшие со строками. Если ты не заметил, то перед тем, как освободить массив, я очищаю память, занятую каждой строкой в массиве.
Кроме того, если присмотрется внимательно к дискуссии, то можно заметить, что я совершенно точно указываю место, где спрятана проблема. Она в первой процедуре.
Люди!!! Не спрашивайте, пожалуйста, что за странный код!!! Это просто макет демонстрирующий проблему. Я не могу выкинуть сюда 150Kb исходников и попросить Вас разобраться.
Если кто-то знает, что добавить в первую процедуру или всю прогу, чтобы память из-под S освобождалась корректно, помогите пожалуйста!!
Fantasist (2002-04-07 02:21:00) [3]Хе-хе. Здорово!
Вот тут Делфи над вами со своей удобной(!) строкой и издевается. :)
Для начала - строка в Делфи - это указатель. Но компилятор все за вас делает так, что вам кажеться что это обыкновенная переменная.
Теперь, возми и вначале процедуры:
procedure TForm1.Button1Click(Sender: TObject);
сделай sizeof(p^). Сделай это и в конце этой процедуры, и сравни размеры. Они одинаковые! А куда же делась память, которую ты выделил для каждой строки? Ага, вот то-то и оно. Твой:
ttry1=array[1..4096] of string; - это массив указателей, и когда ты радостно грохаешь его в своем dispose, то освобождается ровно 4*4096 байт. А все строки остаются висеть в памяти. Не круто ли. :)
MBo (2002-04-06 22:52:00) [4]в этой процедуре выделяется примерно 8 мег памяти
for i:=1 to 4096 do
Begin
setlength(s,i);
p^[i] := s;
setlength(s,0);
End;
khodov (2002-04-06 22:39:00) [5]Не-е. Дело в том, что там не просто строки, а записи, в которых есть строки, указатели на объекты, и т.д. Но проблема возникает только со строками. Я просто не стал делать записи со строками, а сделал статический массив.
Anatoly Podgoretsky (2002-04-06 22:35:00) [6]khodov © (06.04.02 22:20)
Извиняюсь, не обратил внимания
MBo (2002-04-06 22:32:00) [7]А TStringList не подойдет?
khodov (2002-04-06 22:24:00) [8]To Mbo:
А не можете ли Вы чего-нибудь посоветовать. У меня в реальной проге расход памяти доходит до 200Mb в результате этого.
khodov (2002-04-06 22:20:00) [9]To Anatoly Podgoretsky:
Если Вы говорите про строку:
dispose(t[i]);
то я использую dispose не с dynamic-array variable, а с Pointer-ом типа ptry1, что считаю вполне корректным.
Ошибкой было бы использование dispose(t)
Или я ошибаюсь?
MBo (2002-04-06 22:17:00) [10]По-видимому, так -
при расширении дин.массива или строки выделяется новый кусок памяти, а в старый уже не запишешь, т.к. он мал. Вот и накапливается пустое место мелкими порциями
Anatoly Podgoretsky (2002-04-06 22:14:00) [11]Do not apply the dereference operator (^) to a dynamic-array variable or pass it to the New or Dispose procedure.
Это из хелпа
khodov (2002-04-06 22:10:00) [12]Да там реальный код сложнее. Этот - просто макет, который производит ту же утечку, что и реальная прога.
Ну, я знаю, что если в первой процедуре на использовать s, а сразу устанавливать длину для элементов массива, то утечки нету. Так в чем проблема? кто знает?
MBo (2002-04-06 21:39:00) [13]Код довольно экзотический. Что он должен делать?