Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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?



Страницы: 1 вся ветка

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

Наверх





Память: 0.48 MB
Время: 0.006 c
3-57640
Boozmakov
2002-03-24 19:13
2002.04.18
Real-time формирование ConnectionString для ADOConnection


1-57792
Vlr
2002-04-05 20:59
2002.04.18
Легкая перезагрузка Windows.


3-57648
der
2002-03-28 14:35
2002.04.18
Создание таблицы по структуре описанной в ini файле. КАК?


14-57845
Tpv
2002-03-06 23:12
2002.04.18
Зависание программы.


3-57657
ol
2002-03-26 15:38
2002.04.18
чем в sql IB можно работать с датами





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский