Как избавиться от утечки памяти через '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?
От: wallaby  
Дата: 03.09.09 09:01
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Проблема такая:


А>
А>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 не
А>инициализировать, то, естественно, проблем с памятью нет).

Что значит остаётся, чем проверял? Память освобождается если только нет ещё строк, ссылающихся на '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?
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 03.09.09 09:11
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос: Кто должен чистить память, выделенную под 'string'? Если никто, то

А> как мне её освободить самому? Что-то я не нашёл, чтобы эта проблема
А> хоть где-нибудь даже обсуждалась...

1) SetLength().
2) MyString:='';

Хотя по большому счету — нафиг, бо Дельфя сама должна об этом забитится (как тебе уже сказали). И самовольничанием можно выхватить еще кучку спецэффектов, причем далеко не безобидных
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re: Как избавиться от утечки памяти через 'string' в D5?
От: jhfrek Россия  
Дата: 03.09.09 10:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>в результате исполнения этого замечательного кода в памяти остаётся

А>блок, выделенный для этого самого '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?
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 03.09.09 13:19
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Сухой остаток печальный: Это что? Каждый динамический список в программе чистить

А>отдельным кодом?????

Либо делай приведения типов (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 Украина http://www.bdslib.at.ua
Дата: 03.09.09 14:09
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, 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 Украина http://www.bdslib.at.ua
Дата: 04.09.09 07:37
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, 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?
От: Leonidze  
Дата: 01.10.09 20:19
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, DarkMaster


А>Да, похоже без перевода рекордов в классы не обойтись...

А>С общим предком — там всё просто: делфа автоматом суёт во все производные классы свой
А>TObject. Его и достаточно. А что касается перехода с TList на TObjectList, то после
А>перехода на классы, это уже не принципиально. Только и делов, что ручками чистить
А>удаляемый объект....

А отнаследоваться от TList, перегрузить Notify-что-то-там на очистку структуры при удалении
и использовать свой объект-список не пробовали? Пишу по памяти, но сам всегда делал именно так.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.