Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Освобождение памяти [D6]


Страницы:   1 2 3

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]

...никаких вариантов - освобождается.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо