Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.18;
Скачать: [xml.tar.bz2];




Вниз

Люди!!! Ткните мне, пожалуйста, пальцем в утечку памяти. 


khodov   (2002-04-06 21:28) [0]

Я сделал упрощенный пример, который моделирует мою проблему. Вот две процедуры, которые реагируют на кнопки на форме.
Как Вы легко поймете, первая, с каждым новым кликом, создает массив строк, которым присваивает различную длину.
Вторая должна почистить память.
Но в результате, если нажимать по такой схеме:
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;



MBo   (2002-04-06 21:39) [1]

Код довольно экзотический. Что он должен делать?



khodov   (2002-04-06 22:10) [2]

Да там реальный код сложнее. Этот - просто макет, который производит ту же утечку, что и реальная прога.

Ну, я знаю, что если в первой процедуре на использовать s, а сразу устанавливать длину для элементов массива, то утечки нету. Так в чем проблема? кто знает?



Anatoly Podgoretsky   (2002-04-06 22:14) [3]

Do not apply the dereference operator (^) to a dynamic-array variable or pass it to the New or Dispose procedure.

Это из хелпа



MBo   (2002-04-06 22:17) [4]

По-видимому, так -
при расширении дин.массива или строки выделяется новый кусок памяти, а в старый уже не запишешь, т.к. он мал. Вот и накапливается пустое место мелкими порциями



khodov   (2002-04-06 22:20) [5]

To Anatoly Podgoretsky:
Если Вы говорите про строку:
dispose(t[i]);
то я использую dispose не с dynamic-array variable, а с Pointer-ом типа ptry1, что считаю вполне корректным.

Ошибкой было бы использование dispose(t)

Или я ошибаюсь?



khodov   (2002-04-06 22:24) [6]

To Mbo:
А не можете ли Вы чего-нибудь посоветовать. У меня в реальной проге расход памяти доходит до 200Mb в результате этого.



MBo   (2002-04-06 22:32) [7]

А TStringList не подойдет?



Anatoly Podgoretsky   (2002-04-06 22:35) [8]

khodov © (06.04.02 22:20)
Извиняюсь, не обратил внимания



khodov   (2002-04-06 22:39) [9]

Не-е. Дело в том, что там не просто строки, а записи, в которых есть строки, указатели на объекты, и т.д. Но проблема возникает только со строками. Я просто не стал делать записи со строками, а сделал статический массив.



MBo   (2002-04-06 22:52) [10]

в этой процедуре выделяется примерно 8 мег памяти

for i:=1 to 4096 do
Begin
setlength(s,i);
p^[i] := s;
setlength(s,0);
End;



Fantasist   (2002-04-07 02:21) [11]

Хе-хе. Здорово!
Вот тут Делфи над вами со своей удобной(!) строкой и издевается. :)
Для начала - строка в Делфи - это указатель. Но компилятор все за вас делает так, что вам кажеться что это обыкновенная переменная.
Теперь, возми и вначале процедуры:

procedure TForm1.Button1Click(Sender: TObject);

сделай sizeof(p^). Сделай это и в конце этой процедуры, и сравни размеры. Они одинаковые! А куда же делась память, которую ты выделил для каждой строки? Ага, вот то-то и оно. Твой:
ttry1=array[1..4096] of string; - это массив указателей, и когда ты радостно грохаешь его в своем dispose, то освобождается ровно 4*4096 байт. А все строки остаются висеть в памяти. Не круто ли. :)



khodov   (2002-04-07 07:55) [12]

To MBo:
Я знаю, что 8 мег выделяется.

To Fanatist:
Спасибо за вводный курс лекций :). Я имею дело с Delphi начиная с 1-й версии и даже раньше :). За это время я успел изучить изменения, произошедшие со строками. Если ты не заметил, то перед тем, как освободить массив, я очищаю память, занятую каждой строкой в массиве.
Кроме того, если присмотрется внимательно к дискуссии, то можно заметить, что я совершенно точно указываю место, где спрятана проблема. Она в первой процедуре.

Люди!!! Не спрашивайте, пожалуйста, что за странный код!!! Это просто макет демонстрирующий проблему. Я не могу выкинуть сюда 150Kb исходников и попросить Вас разобраться.

Если кто-то знает, что добавить в первую процедуру или всю прогу, чтобы память из-под S освобождалась корректно, помогите пожалуйста!!



Fantasist   (2002-04-07 09:17) [13]

2khodov:
:)
Опс... Облом. А так хотелось кого-то поучить. Без наездов. :)


> Если ты не заметил, то перед тем, как освободить массив,
> я очищаю память, занятую каждой строкой в массиве.


Заметил. А потом забыл.
Попробую посмотреть по внимательнее.

А все-таки, а не пробывал ли ты то же самое сделать через PChar?




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.18;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.74 MB
Время: 0.027 c
1-57682           REA                   2002-03-25 10:34  2002.04.18  
Размер EXE. Опять размер


1-57719           gray1                 2002-04-08 12:54  2002.04.18  
работа с ексель-файлами из делфи


6-57826           Stanislav             2002-02-06 13:17  2002.04.18  
Изменение настроек WebBrowser


14-57861          Mystic                2002-03-08 15:39  2002.04.18  
Дети


1-57803           Тема                  2002-04-06 15:29  2002.04.18  
С чего начать???