查找最大的可用内存块 [英] Find largest free memory block

查看:120
本文介绍了查找最大的可用内存块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时碎片会耗尽内存.

是否可以找到最大的空闲内存块? 我将Delphi 2007与FastMM一起使用.在Windows 2003上运行Windows XP的应用程序上进行开发.

致谢

我可以添加有关该应用程序正在Windows Server 2003 x64上具有32 GB内存的服务器上运行的信息.但是该应用程序是32位应用程序,因此每个实例的理论上最大分配内存为2 GB.一次运行许多实例.我认为总的物理内存不足.我猜想启动该应用程序时会获得32位虚拟内存空间.这样在运行时可能会变得过于分散.

我还找到了FastGetHeapStatus方法,该方法返回一个THeapStatus以及一些用于释放内存的字段.也许我可以用那些.

我发现了这个如何获取最大的可用连续内存块. 代码是C,但也许可以将其翻译为Delphi.

解决方案

这是您想要的Delphi代码翻译:

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;

您可以像这样使用它:

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;

请注意,我必须从最大大小中减去16个字节,大概是因为动态数组本身使用了从同一块内存中分配的几个字节,所以下一个分配基于下一个16的倍数. /p>

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.

解决方案

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.

这篇关于查找最大的可用内存块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆