开发者

Why use FreeMem/Dispose routines to release memory, but there is no memory reduces?

I use AllocMem/GetMem/New routines to allocate memory, then use FreeMem/Dispose routines to release memory. But I found(by Process Explorer) that memory size of the process not reduced.

If I use GlobalAllocPtr/HeapAlloc and Gl开发者_如何学运维obalFreePtr/HeapFree APIs, the memory size will reduced.

Here is my test code:

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;


That is how Delphi memory manager works - it supports it's own memory cache so that it does not return every freed memory back to system, but holds it in the cache. Next time then it allocates a memory it tries first to find the requested memory in the cache, not in system. That makes memory allocation/deallocation faster.

BTW never use FreeMem for records with lifetime managed fields (ex strings, as in your example) - it leads to memory leaks. Use Dispose instead.

Also never use GetMem for records with lifetime managed fields (commented line in your example) - it leads to access violations. Use New.


You're seeing this because getting memory from Windows is an expensive operation, so when you use Delphi's built in memory manager, it caches a certain amount of unused memory since you're likely to need it again for something else soon.

If you free a lot of memory you'll probably see it give some back to the operating system, but it still keeps some of it around locally so it won't have to ask for more as soon.


The Delphi's memory manager actually allocates/frees memory by pages.


You should not specify Size to FreeMem function. It takes only one parameter - pointer. Otherwise your code looks just fine. I just wonder - why are you using malloc and free instead of new and delete/dispose? Or GetMem and FreeMem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜