我使用AllocMem / GetMem / New例程来分配内存,然后使用FreeMem / Dispose例程来释放内存。但我发现(通过Process Explorer)进程的内存大小没有减少。
如果我使用GlobalAllocPtr / HeapAlloc和GlobalFreePtr / HeapFree API,内存大小将会减少。
这是我的测试代码:
type
TMyRec = record
Name: string;
TickCount: Cardinal;
Buf: array[0..1024 - 1] of byte;
end;
PMyRec = ^TMyRec;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormDestroy(Sender: TObject);
begin
FList.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FList := TList.Create;
ReportMemoryLeaksOnShutdown := true;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
Size: Integer;
Rec: PMyRec;
Heap: Cardinal;
begin
Size := SizeOf(TMyRec);
Heap := GetProcessHeap;
for I := 0 to 2000 - 1 do
begin
Rec := AllocMem(Size); // Delphi routine
//GetMem(Rec, Size); // Delphi routine
//New(Rec); // Delphi routine
//Rec := GlobalAllocPtr(GPTR, Size); // Windows API
//Rec := HeapAlloc(Heap, HEAP_ZERO_MEMORY, Size); // Windows API
FList.Add(Rec);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i: Integer;
Size: Integer;
Rec: PMyRec;
Heap: Cardinal;
begin
Size := SizeOf(TMyRec);
Heap := GetProcessHeap;
for i := FList.Count - 1 downto 0 do
begin
Rec := PMyRec(FList.Items[i]);
FreeMem(Rec, Size); // Delphi routine
//Dispose(Rec); // Delphi routine
//GlobalFreePtr(Rec); // Windows API
//HeapFree(Heap, 0, Rec); // Windows API
end;
FList.Clear;
end;
答案 0 :(得分:24)
这就是Delphi内存管理器的工作方式 - 它支持自己的内存缓存,因此它不会将每个释放的内存返回给系统,而是将其保存在缓存中。下次它会分配一个内存,它首先尝试在缓存中找到请求的内存,而不是在系统中。这使得内存分配/释放更快。
BTW永远不会将FreeMem
用于具有生命周期管理字段的记录(例如字符串中的ex字符串) - 它会导致内存泄漏。请改用Dispose
。
也永远不要将GetMem
用于带有生命周期管理字段的记录(示例中的注释行) - 这会导致访问冲突。使用New
。
答案 1 :(得分:11)
你看到了这一点,因为从Windows获取内存是一项昂贵的操作,因此当你使用Delphi的内置内存管理器时,它会缓存一定数量的未使用内存,因为很可能很快就需要它。
如果你释放了大量内存,你可能会看到它会给操作系统带来一些回复,但是它仍然会在本地保留一些,所以它不需要更快地要求更多。
答案 2 :(得分:2)
Delphi的内存管理器实际上是按页面分配/释放内存。
答案 3 :(得分:1)
您不应将Size指定为FreeMem函数。它只需要一个参数 - 指针。 否则你的代码看起来很好。 我只是想知道 - 为什么你使用malloc和free而不是new和delete / dispose?或者GetMem和FreeMem。