![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Освобождение памяти [D6]
SashaK © (2002-08-13 14:05:00)У меня есть массив из записей (Record). Запись имеет строковые поля. Когда я присваиваю в строковое поле значение, очевидно, выделяется память и туда пишется строка. Будет ли при удалении массива освобождаться память, выделенная под строки ?
kull (2002-08-13 17:13:00) [21]
>
> Digitman © (13.08.02 17:08)
Ну нет, это не вариант, PChar это не string.
Сам выделяешь сам и освобождай, здесь за тебя Delphi ничего не сделает. Это все равно что ^Integer.
Digitman (2002-08-13 17:12:00) [22]>kull
Все то, что я знаю (если я чего-то знаю), дает мне "чистый" вообще и машкод в окне CPU в частности. Никакими сторонними средствами я никогда не пользовался, не пользуюсь и пользоваться не намерен - доверяю только Борланду и своей голове.
DiamondShark (2002-08-13 17:09:00) [23]
> kull © (13.08.02 17:04)
Системный монитор -- плохой помошник.
Менеджер памяти Дельфи выделяет большой непрерывный кусок для кучи и уже в нем сам себе на уме распределяет строки и объекты.
Только когда этот кусок закончится, системный монитор покажет большой скачок в выделенной памяти -- дельфевый менеджер вышел на охоту.
Skier (2002-08-13 17:09:00) [24]Ребята, мы тут спорим, а автор-то - молчит:)))
Digitman (2002-08-13 17:08:00) [25]Приношу извинения. Действительно, в этом примере утечки не будет - компилятор вставляет неявный код LStrClr в FinalizeArray(). Проглядел, проскачив мимо Finalize().
Ок. Вот еще вариант :
type
prec = ^trec;
trec = record
s: PChar; // чем не вариант строкового типа ?
end;
var
rec: prec;
..
s1:= "XXX";
new(rec);
rec.s := SysGetMem(..);
strcopy(rec.s, ...);
dispose(rec);
вот и утечка ! а ведь - тоже вариант
kull (2002-08-13 17:07:00) [26]Нет, народ, вы меня просто удивляете - трассировка, CPU, ...
На фига все это нужно?
Любой ламер может проверить этот код на утечку обыкновенными стандартными средствами....
kull (2002-08-13 17:04:00) [27]2 Digitman
Я конечно понимаю что вы - иастер, но зачем такие сложности?
Трассировка, изучение исходного кода.
Все проверяется простым виндовским системным монитором.
1. берем ваш пример и добавляем SetLength:
procedure TForm1.Button1Click(Sender: TObject);
type
prec = ^trec;
trec = record
s: string;
end;
var
rec: prec;
s1: string;
begin
SetLength(s1,1000000);
new(rec);
rec.s := s1;
dispose(rec);
end;
2. Запускаем системный монитор и при нажатии на Button1 не видим никакого изменения в объеме памяти.
если же dispose убрать, то изменение будет заметно не вооруженным глазом.
Сомневаюсь что в D5 Borland мог так налажать...
DiamondShark (2002-08-13 17:04:00) [28]А Ученик прав.
Dispose учитывает неявный параметр -- тип переменной.
На стадии компиляции, естественно.
DiamondShark (2002-08-13 17:00:00) [29]Эх, господа теоретики!
Ну вы хоть перед тем как посты слать, проверьте, что пишите!
> Digitman © (13.08.02 16:21)
> >kull
>
> Неверно. Нижеследующий вариант
> <...>
> дает 100%-ю утечку
Что по вашему выдаст этот код
type
TRec = record
a: integer;
s: string;
end;
PRec = ^TRec;
var
R: PRec;
H: THeapStatus;
f1, f2: cardinal;
S1: string;
begin
S1 := "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
H := GetHeapStatus;
f1 := H.TotalFree;
New(R);
R.s := S1;
Dispose(R);
H := GetHeapStatus;
f2 := H.TotalFree;
ShowMessageFmt("%d, %d", [F1, F2]);
end;
Или в CPU потрассируйте, убедитесь в вызове Finalize
Dispose работает корректно, так как учитывает тип.
А вот FreeMem даст утечку.
> SashaK (13.08.02 14:38)
Тогда придется вызывать Finalize с приведением типов.
пример:
type
TRec = record
a: integer;
s: string;
end;
TBuffer = array[0..0] of TRec;
PBuffer = ^TBuffer;
...
var
ByteSize: cardinal;
Buffer: pointer;
begin
ByteSize := GetNeededBufferSize;
GetMem(Buffer, ByteSize);
FillChar(Buffer^, ByteSize, 0); //Желательно
...
// какие-то действия, в том числе
PBuffer(Buffer)[i].s := "zzzzzzzzzzzzzzzzzzzzzzzzz";
...
Finalize(TRec(Buffer^), ElementCount); //Явный тип !!!
FreeMem(Buffer, ByteSize);
// теперь все чисто
end;
Ученик (2002-08-13 16:53:00) [30]Это было из Delphi 5.0
Ученик (2002-08-13 16:53:00) [31]procedure _Dispose{ p: Pointer; typeInfo: Pointer};
asm
{ -> EAX Pointer to object to be disposed }
{ EDX Pointer to type info }
PUSH EAX
CALL _Finalize
POP EAX
CALL _FreeMem
end;
procedure _Finalize{ p: Pointer; typeInfo: Pointer};
asm
MOV ECX,1
JMP _FinalizeArray
end;
procedure _FinalizeArray{ p: Pointer; typeInfo: Pointer; elemCount: Longint};
asm
{ -> EAX pointer to data to be finalized }
{ EDX pointer to type info describing data }
{ ECX number of elements of that type }
CMP ECX, 0 { no array -> nop }
JE @@zerolength
....
Ученик (2002-08-13 16:51:00) [32]>Digitman © (13.08.02 16:46)
Или проще по исходникам System.pas
Digitman (2002-08-13 16:50:00) [33]>kull
У меня - Д5.5
Просто отртрассировал этот код в окне CPU - нет ни одного SysFreeMem(), соответствующего предыдущему SysGetMem() для строкового поля при операции присвоения.
То же самое, если угодно, можно увидеть и в system.pas/sysutils.pas
Skier (2002-08-13 16:48:00) [34]>Digitman
Извините, Мастер, но Вы не правы Dispose освободит
и строку...
Ученик (2002-08-13 16:47:00) [35]>Digitman © (13.08.02 16:46)
Пройдитесь в отладчике при Dispose
Digitman (2002-08-13 16:46:00) [36]>Ученик
С какой это стати ? Менеджер памяти, выполняющий Dispose() для блока памяти, отведенной ранее под структуру rec вызовом New(), ничего не знает о ее содержимом - менеджеру передается лишь указатель на некий блок памяти, который, в свою очередь содержит не просто какие-то статические данные в виде 4-байтного поля TRec.s, а 4 байта как указатель на динамическую строковую структуру. Память под эта самую строковую структуру была выделена неявным вызовом SysGetMem() в контексте исполнения строки rec.s := s1.
Приводи контраргументы и убеди меня в моей ошибке.
kull (2002-08-13 16:42:00) [37]
> Digitman © (13.08.02 16:21)
Неверно. Как ты определил утечку?
Никакой утечки в этом примере нет, даже если сделать
SetLength(s1,1000).
Проверено Memory Sleuth 2.
Ученик (2002-08-13 16:27:00) [38]>Digitman
В Delphi 6 память освобождается Dispose
Digitman (2002-08-13 16:21:00) [39]>kull
Неверно. Нижеследующий вариант
type
prec = ^trec;
trec = record
s: string;
end;
var
rec: prec;
s1: string;
..
s1:= "XXX";
new(rec);
rec.s := s1;
dispose(rec);
дает 100%-ю утечку
kull (2002-08-13 16:11:00) [40]...никаких вариантов - освобождается.