Как избавиться от утечки памяти через 'string' в D5?
От:
Аноним
Дата:
03.09.09 08:41
Оценка:
Всем доброго времени суток!
Кто знает — есть ли какие нибудь средства принудительного освобождения памяти,
занимаемой переменной типа 'string'?
Проблема такая:
type
TTestRec = record
Ident: integer ;
Name: string ;
end;
var
tr: ^TTestRec ;
begin
New ( tr ) ;
tr^.Name := 'bla-bla-bla' ;
......
Dispose ( tr ) ;
в результате исполнения этого замечательного кода в памяти остаётся
блок, выделенный для этого самого 'bla-bla-bla'! (Если поле Name не
инициализировать, то, естественно, проблем с памятью нет).
Вопрос: Кто должен чистить память, выделенную под 'string'? Если никто, то
как мне её освободить самому? Что-то я не нашёл, чтобы эта проблема
хоть где-нибудь даже обсуждалась...
Re: Как избавиться от утечки памяти через 'string' в D5?
А>в результате исполнения этого замечательного кода в памяти остаётся А>блок, выделенный для этого самого 'bla-bla-bla'! (Если поле Name не А>инициализировать, то, естественно, проблем с памятью нет).
Что значит остаётся, чем проверял? Память освобождается если только нет ещё строк, ссылающихся на 'bla-bla-bla' — строки в Delphi "reference counted".
При наличии таких строк после вызова Dispose ( tr ) у 'bla-bla-bla' декрементируется счётчик ссылок.
А>Вопрос: Кто должен чистить память, выделенную под 'string'? Если никто, то А> как мне её освободить самому?
В данном случае память под 'string' освобождает процедура finalize, вызываемая внутри Dispose. Вызывать эту процедуру явно самому нет надобности.
А> Что-то я не нашёл, чтобы эта проблема А> хоть где-нибудь даже обсуждалась...
Видимо потому что нет такой проблемы.
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
Re: Как избавиться от утечки памяти через 'string' в D5?
Здравствуйте, Аноним, Вы писали:
А>Вопрос: Кто должен чистить память, выделенную под 'string'? Если никто, то А> как мне её освободить самому? Что-то я не нашёл, чтобы эта проблема А> хоть где-нибудь даже обсуждалась...
1) SetLength().
2) MyString:='';
Хотя по большому счету — нафиг, бо Дельфя сама должна об этом забитится (как тебе уже сказали). И самовольничанием можно выхватить еще кучку спецэффектов, причем далеко не безобидных
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re: Как избавиться от утечки памяти через 'string' в D5?
Здравствуйте, Аноним, Вы писали:
А>в результате исполнения этого замечательного кода в памяти остаётся А>блок, выделенный для этого самого 'bla-bla-bla'! (Если поле Name не А>инициализировать, то, естественно, проблем с памятью нет).
либо глючит анализатор утечек, либо у вас где-то живут ссылки на tr^.Name, либо вы где-то делаете fillchar(tr^,..) убивая счетчик ссылок на стринг
Re: Как избавиться от утечки памяти через 'string' в D5?
От:
Аноним
Дата:
03.09.09 12:45
Оценка:
Спасибо, я нашёл в чём дело.
На самом деле, я слегка ввёл в заблуждение уважаемую публику (просто было лень вводить длинный код примера):
У меня в программе создаются куча динамических массивов из структур, подобных приведённой:
list := TList.Create ;
for i := 0 to NNN do
begin
New ( tr ) ;
tr^.Name := 'bla-bla-bla' ;
list.Add ( tr ) ;
end ;
//
// а после использования такие списки освобождаются универсальной процедурой очистки
// одноуровневых списков, типа:for i := list.Count - 1 do
Dispose ( list.Items[i] ) ;
list.Free ;
// вот тут то память и не освобождается.
// а проблема - в непоименованном указателе в процедуре Dispose.
// Если Dispose указать тип освобождаемой записи, то память, занятая
// под string, освобождаетсяfor i := list.Count - 1 do
begin
tr := list.Items[i] ; // вот так всё работает
Dispose ( tr ) ; // как надо!end ;
list.Free ;
Сухой остаток печальный: Это что? Каждый динамический список в программе чистить
отдельным кодом?????
Я тут по-быстрому накидал тот-же код, только вместо record'а создал class с полем 'Name: string'.
Загнал их в список, а потом почистил этот список как список потомков общего дельфийского
класса предка TObject. Это работает. В классах пергружаемый деструктор освобождает память поля
string, даже если я в деструкторе своего производного класса не освобождаю её сам (Name := '').
Только переделывать весь код под классы тоже оченно не хочется — прога то больша-а-а-а-я.
Так что, что делать так и не понятно.
Спасибо всем, кто откликнулся!
Re[2]: Как избавиться от утечки памяти через 'string' в D5?
Здравствуйте, Аноним, Вы писали:
А>Сухой остаток печальный: Это что? Каждый динамический список в программе чистить А>отдельным кодом?????
Либо делай приведения типов (Dispose(TMyRecord(List.Items[i])) либо переходи на обьекты. Второе — легче.
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re[3]: Как избавиться от утечки памяти через 'string' в D5?
От:
Аноним
Дата:
03.09.09 13:42
Оценка:
Здравствуйте, DarkMaster, Вы писали:
DM>Здравствуйте, Аноним, Вы писали:
А>>Сухой остаток печальный: Это что? Каждый динамический список в программе чистить А>>отдельным кодом?????
DM>Либо делай приведения типов (Dispose(TMyRecord(List.Items[i])) либо переходи на обьекты. Второе — легче.
Cпасибо, не говоря о том, что транслятор на Dispose(TMyRecord(List.Items[i])) выдаёт 'invalid typecast',
сам механизм передачи типа записи в процедуру внушает некий трепет ...
Re[4]: Как избавиться от утечки памяти через 'string' в D5?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, DarkMaster, Вы писали:
DM>>Здравствуйте, Аноним, Вы писали:
А>>>Сухой остаток печальный: Это что? Каждый динамический список в программе чистить А>>>отдельным кодом?????
DM>>Либо делай приведения типов (Dispose(TMyRecord(List.Items[i])) либо переходи на обьекты. Второе — легче.
А>Cпасибо, не говоря о том, что транслятор на Dispose(TMyRecord(List.Items[i])) выдаёт 'invalid typecast', А>сам механизм передачи типа записи в процедуру внушает некий трепет ...
Какого типа? Это у меня очепятка (к классам привычка сказалась) — тут не тип передавать, а типизированный указатель.
type
PMyRecord=^TMyRecord;
TMyRecord=packed record
A,B,C:integer;
AName:string;
end;
var FList:TList;
procedure CreateList;
var i:integer;
P:PMyRecord;
begin
FList:=TList.Create;
for i:=0 to 100 do
begin
New(P);
P^.A:=i;
P^.B:=i+1;
P^.C:=i+2;
P^.AName:='Name'+IntToStr(i);
FList.Add(P);
end;
end;
procedure DisposeList;
var i:integer;
begin
for i:=0 to Pred(FList.Count) do
Dispose(PMyRecord(FList.Items[i]));
FList.Free;
end;
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re[5]: Как избавиться от утечки памяти через 'string' в D5?
От:
Аноним
Дата:
04.09.09 05:14
Оценка:
Здравствуйте, DarkMaster
Как я уже писал, у меня D5 на конструкцию Dispose(PMyRecord(FList.Items[i])) ругается инвалидным приведением типов.
А что касается трепета при передаче типа, я имел в виду, что у меня эта процедура освовождения списков освобождает
массивы нескольких десятков типов. Единственный вариант, который просматривается, — это подвешивать к каждому типу
record'а некий идентификатор, котрый и передавать в DisposeList вместе с массивом, а в самой процедуре громоздить
некий "могучий" case. А с учётом нежелания Dispose съедать приведение типов, придется освобождать рекорд через
присваивание его указателю соответствующего типа. Или это можно сделать как-то проще?
Re[6]: Как избавиться от утечки памяти через 'string' в D5?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, DarkMaster
А>Как я уже писал, у меня D5 на конструкцию Dispose(PMyRecord(FList.Items[i])) ругается инвалидным приведением типов. А>А что касается трепета при передаче типа, я имел в виду, что у меня эта процедура освовождения списков освобождает А>массивы нескольких десятков типов. Единственный вариант, который просматривается, — это подвешивать к каждому типу А>record'а некий идентификатор, котрый и передавать в DisposeList вместе с массивом, а в самой процедуре громоздить А>некий "могучий" case. А с учётом нежелания Dispose съедать приведение типов, придется освобождать рекорд через А>присваивание его указателю соответствующего типа. Или это можно сделать как-то проще?
Насчет ругани не знаю — у Д6 самая старая, а ставить Д5 для проверки — неохота. Ну а для освобождения структур в одном месте и по-простому:
1) Переведи структуры на классы
2) Все классы отнаследуй от одного предка для унификации.
3) Используй TObjectList вместо TList — второй за собой все обьекты в нем и уберет.
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re[7]: Как избавиться от утечки памяти через 'string' в D5?
От:
Аноним
Дата:
04.09.09 10:12
Оценка:
Здравствуйте, DarkMaster
Да, похоже без перевода рекордов в классы не обойтись...
С общим предком — там всё просто: делфа автоматом суёт во все производные классы свой
TObject. Его и достаточно. А что касается перехода с TList на TObjectList, то после
перехода на классы, это уже не принципиально. Только и делов, что ручками чистить
удаляемый объект....
Re[8]: Как избавиться от утечки памяти через 'string' в D5?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, DarkMaster
А>Да, похоже без перевода рекордов в классы не обойтись... А>С общим предком — там всё просто: делфа автоматом суёт во все производные классы свой А>TObject. Его и достаточно. А что касается перехода с TList на TObjectList, то после А>перехода на классы, это уже не принципиально. Только и делов, что ручками чистить А>удаляемый объект....
А отнаследоваться от TList, перегрузить Notify-что-то-там на очистку структуры при удалении
и использовать свой объект-список не пробовали? Пишу по памяти, но сам всегда делал именно так.