Find largest free memory block

delphi, memory-management

Solution

This is the translation to Delphi code that you wanted:

function GetLargestFreeMemRegion(var AAddressOfLargest: pointer): LongWord;
var
  Si: TSystemInfo;
  P, dwRet: LongWord;
  Mbi: TMemoryBasicInformation;
begin
  Result := 0;
  AAddressOfLargest := nil;
  GetSystemInfo(Si);
  P := 0;
  while P < LongWord(Si.lpMaximumApplicationAddress) do begin
    dwRet := VirtualQuery(pointer(P), Mbi, SizeOf(Mbi));
    if (dwRet > 0) and (Mbi.State and MEM_FREE <> 0) then begin
      if Result < Mbi.RegionSize then begin
        Result := Mbi.RegionSize;
        AAddressOfLargest := Mbi.BaseAddress;
      end;
      Inc(P, Mbi.RegionSize);
    end else
      Inc(P, Si.dwPageSize);
  end;
end;

You can use it like this:

procedure TForm1.FormCreate(Sender: TObject);
var
  BaseAddr: pointer;
  MemSize: LongWord;
begin
  MemSize := GetLargestFreeMemRegion(BaseAddr);
  // allocate dynamic array of this size
  SetLength(fArrayOfBytes, MemSize - 16);

  Caption := Format('Largest address block: %u at %p; dynamic array at %p',
    [MemSize, BaseAddr, pointer(@fArrayOfBytes[0])]);
end;

Note that I had to subtract 16 bytes from the maximum size, presumably because the dynamic array itself uses a few bytes which were allocated from the same chunk of memory, so the next allocation was based on the next multiple of 16.

Problem

There is sometimes a problem with running out of memory when it got fragmented. Is it possible to find the largest free memoryblock ? I use Delphi 2007 with FastMM. Developing on Windows XP running app on Windows 2003. Regards EDIT: I could add the info that the app is running on a server with 32 GB memory on a Windows Server 2003 x64. But the app is a 32 bit application so the theoretical max allocated memory for each instance is 2 GB. Many instances is run at once. I do not think it is the total physical memory that is to little. I guess when started the app got a 32 bit virtual memory space. This can then be too fragmented during runtime. I also found the method FastGetHeapStatus that returns a THeapStatus with some fields for free memory. Maybe I could use those. EDIT2: I found this How to get the largest available continues memory block. The code is C but maybe it could be translated to Delphi.

Original source