![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Когда освободиться TStrings ? [D7, XP]
Альф © (2009-05-13 10:40:00)Простите за немножко дурацкий вопрос :)
Ситуация такая - есть функция вида
function CreateStringList(const Value: string): TStrings;
var
i: integer;
begin
result := TStringList.Create();
try
// Тут заполняем список в зависимости от условий
for i := 0 to 9 do result.Append(IntToStr(i));
except
result.Free();
raise;
end;
end;
При таком вызове понятно когда создастся и освободиться список из CreateStringList
var
sl: TStrings;
begin
sl := CreateStringList('*.txt');
Memo.Lines.Assign(sl);
sl.Free();
end;
А вот когда освободиться этот список при таком вызове ?
Memo.Lines.Assign(CreateStringList('*.txt');
Григорьев Антон (2009-05-14 08:46:00) [1]
> Альф (13.05.09 11:34) [8]
> Думаю можно было бы при нормальном завершении программы
> проверять созданные объекты и вызывать Free для неосвобождённых.
В имеющейся реализации - нельзя. С точки зрения менеджера памяти объект - это просто выделенный блок. Менеджер не знает, что находится в этом блоке - объект или просто данные. Поэтому, даже обнаружив утечку, не имеет возможности решить, нужно здесь вызывать Free или нет.
Sapersky (2009-05-13 14:49:00) [2]Ну вот ещё вариант StringList с автоматическим освобождением:
http://edn.embarcadero.com/article/33423
В старых версиях вместо record можно использовать object.
Anatoly Podgoretsky (2009-05-13 14:47:00) [3]
> Так а я о чём :)
Тогда первый вариант
Игорь Шевченко (2009-05-13 14:33:00) [4]
> Но припустим есть наследник TStringList, который будет создавать
> временный файл на диске, и удалять его в деструкторе. Т.
> е. при невызове нового Free() файл так и останется.
Даже если это будет не наследник TStringList, если деструктор не будет вызван, файл таки останется
Альф (2009-05-13 14:12:00) [5]
> Anatoly Podgoretsky © (13.05.09 13:07) [18]
> не надо выдумывать за меня, я говорил только про :=
Так а я о чём :)
Anatoly Podgoretsky (2009-05-13 13:07:00) [6]> Альф (13.05.2009 12:29:14) [14]
не надо выдумывать за меня, я говорил только про :=
Альф (2009-05-13 12:45:00) [7]
> Игорь Шевченко © (13.05.09 12:31) [16]
> Альф (13.05.09 12:29) [14]
> Строки - управляемый тип, в отличие от классов.
Я немножко не об этом.
Вот есть класс TStringList, деструктор которого освобождает список строк в памяти. Т.е. вызов/невызов TStringList.Free() при завершении программы некритичен.
Но припустим есть наследник TStringList, который будет создавать временный файл на диске, и удалять его в деструкторе. Т.е. при невызове нового Free() файл так и останется.
Игорь Шевченко (2009-05-13 12:31:00) [8]Альф (13.05.09 12:29) [14]
Строки - управляемый тип, в отличие от классов.
Palladin (2009-05-13 12:31:00) [9]
> Альф (13.05.09 12:29) [14]
> Думал - можно ли этот принцип, кроме списка строк, распространить
> на другие классы.
Конечно. Если не устанешь обертки писать )
Альф (2009-05-13 12:29:00) [10]
> Palladin © (13.05.09 11:55) [12]
> И что что не будет вызван? Что дальше то?
Да уже ничего :) безполезно мерять температуру у трупа :)
Думал - можно ли этот принцип, кроме списка строк, распространить на другие классы.
> Anatoly Podgoretsky © (13.05.09 12:02) [13]
> Никакого копирования строк нет, это просто присвоение указателя
Так то оно так - но
procedure TCustomMemo.SetLines(Value: TStrings);
begin
FLines.Assign(Value);
end;
затем
procedure TStrings.Assign(Source: TPersistent);
...
AddStrings(TStrings(Source));
...
end;
я то понимаю что само содержимое строк не копируется, но всёже и не просто присвоение указателя...
Anatoly Podgoretsky (2009-05-13 12:02:00) [11]> Альф (13.05.2009 11:52:11) [11]
Никакого копирования строк нет, это просто присвоение указателя
Palladin (2009-05-13 11:55:00) [12]И что что не будет вызван? Что дальше то?
Альф (2009-05-13 11:52:00) [13]
> Anatoly Podgoretsky © (13.05.09 11:43) [9]
> Только надо проверить по генофонду, освобождается ли старый список при присваивание, иначе вручную освободить.
По генофонду не освобождается - там просто копирование строк из источника в приёмник.
> Palladin © (13.05.09 11:45) [10]
> При нормально завершении программы освободится все и твой лист не останется. Даже если ты потерял ссылку. За это не волнуйся.
Дело вот в чём:
> Григорьев Антон © (13.05.09 10:42) [1]
> Да и то деструктор так и не будет вызван.
Думаю это более важно.
Palladin (2009-05-13 11:45:00) [14]
> Думаю можно было бы при нормальном завершении программы
При нормально завершении программы освободится всеи твой лист не останется. Даже если ты потерял ссылку. За это не волнуйся.
Anatoly Podgoretsky (2009-05-13 11:43:00) [15]Можно так
s := CreateStringList('*.txt');
s := Memo.Lines.Assign(S);
s.Free
или
Memo.Lines := CreateStringList('*.txt');
Только надо проверить по генофонду, освобождается ли старый список при присваивание, иначе вручную освободить.
Альф (2009-05-13 11:34:00) [16]
> Palladin © (13.05.09 11:09) [5]
> Каким образом он должен это делать? Хотя конечно, можно поступить и так:
Думаю можно было бы при нормальном завершении программы проверять созданные объекты и вызывать Free для неосвобождённых.
> Григорьев Антон © (13.05.09 11:15) [6]
> Менеджер памяти, который используется, начиная с BDS2006, отслеживает. Можно получить отчёт о неосвобождённой памяти после завершения программы.
Больше интересовала не память, а именно правильное освобождение объекта.
Альф (2009-05-13 11:24:00) [17]Спасибо
Григорьев Антон (2009-05-13 11:15:00) [18]
> Альф (13.05.09 11:01) [3]
> Т.е. список "уходит в закат" и компилятор, получается, никак
> не отслеживает такие ситуации...
Менеджер памяти, который используется, начиная с BDS2006, отслеживает. Можно получить отчёт о неосвобождённой памяти после завершения программы.
Palladin (2009-05-13 11:09:00) [19]Каким образом он должен это делать? Хотя конечно, можно поступить и так:
Procedure lw(Const s:String);
Begin
Form1.Memo1.Lines.Add(s);
Application.ProcessMessages;
End;
Type
IStrings=Interface
Function GetStrings:TStrings;
End;
Type
TStringsIfc=Class(TInterfacedObject,IStrings)
Private
m_theSL:TStringList;
Public
Constructor Create;
Destructor Destroy; Override;
Function GetStrings:TStrings;
End;
Function TStringsIfc.GetStrings;
Begin
Result:=m_theSL;
End;
Constructor TStringsIfc.Create;
Begin
lw('Constructor TStringsIfc.Create');
m_theSL:=TStringList.Create;
End;
Destructor TStringsIfc.Destroy;
Begin
lw('Destructor TStringsIfc.Destroy');
m_theSL.Free;
End;
Function CreateStrings:IStrings;
Begin
Result:=TStringsIfc.Create;
With Result.GetStrings Do
Begin
Add('1');
Add('2');
End;
End;
procedure TForm1.Button1Click(Sender: TObject);
begin
lw('button click in');
Memo2.Lines.AddStrings(CreateStrings.GetStrings);
lw('button click out');
end;
oldman (2009-05-13 11:05:00) [20]
> Альф (13.05.09 11:01) [3]
> и компилятор, получается, никак не отслеживает такие ситуации...
А оно ему надо?