- Код: Выделить всё
- {$MODE OBJFPC}
 type
 TObj = object
 S: AnsiString;
 constructor Init(const Value: AnsiString);
 destructor Done; virtual;
 end;
 constructor TObj.Init(const Value: AnsiString);
 begin
 S := Value;
 end;
 destructor TObj.Done;
 begin
 end;
 var
 P: Pointer;
 begin
 P := GetMem(SizeOf(TObj));
 TObj(P^).Init(ParamStr(0) + ' (modification)'); // <- созданная тут строка утечёт
 TObj(P^).Done;
 FreeMem(P);
 end.
На первый взгляд с кодом всё в порядке: память из-под объекта мы в конце удаляем, а для создания и уничтожения используем честные конструктор и деструктор. Но в коде есть упомянутая утечка памяти:
- Код: Выделить всё
- D:\data\temp>fpc -gh -gl m.pas && m.exe
 Free Pascal Compiler version 3.0.4 [2017/10/06] for i386
 Copyright (c) 1993-2017 by Florian Klaempfl and others
 Target OS: Win32 for i386
 Compiling m.pas
 Linking m.exe
 26 lines compiled, 0.1 sec, 46704 bytes code, 1908 bytes data
 Heap dump by heaptrc unit
 3 memory blocks allocated : 85/88
 2 memory blocks freed : 39/40
 1 unfreed memory blocks : 46
 True heap size : 163840 (80 used in System startup)
 True free heap : 163632
 Should be : 163648
 Call trace for block $034B15C0 size 46
 $004015AA main, line 23 of m.pas
Как я понимаю данную проблему: деструктор считается обычной процедурой (легаси от Turbo Pascal), поэтому он не приводит к освобождению строки и она утекает.
В данном конкретном случае проблема решается заменой GetMem и FreeMem на New и Dispose. Но представим себе несколько других ситуаций, когда New не поможет:
1. Я хочу выделить память сразу под 100 объектов одним вызовом GetMem
2. Я размещаю объекты в некотором пуле, какие именно - станет известно в рантайме
Как мне правильно уничтожать объекты в подобных ситуациях? Может есть какой-нибудь MODESWITCH, который делает так, что деструктор освобождает все управляемые поля в объекте?





