为什么使用FreeMem / Dispose例程释放内存,但没有内存减少?

时间:2011-04-03 14:55:09

标签: delphi memory

我使用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;

4 个答案:

答案 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。