1

使用VirtualAllocする場合、メモリ管理を簡素化するために次のプロパティを (ab) 使用できます。

仮想アドレスが実際にアクセスされない限り、または実際にアクセスされるまで、実際の物理ページは割り当てられません。

次のコードを実行して、ブロックを割り当てます。

type
  PArrayMem = ^TArrayMem;    //pointer
  TArrayMem = packed record  //as per documentation
    RefCount: Integer;
    Length: NativeInt;
    Elements: Integer;
  end;

var
  a: array of integer;  //dynamic array, structure see above

procedure TForm38.Button1Click(Sender: TObject);
const
  AllocSize = 1024 * 1024 * 1024; //1 GB
var
  ArrayMem: PArrayMem;
begin
  //SetLength(a, 1024*1024*1024); //1G x 8*16
  ArrayMem:= VirtualAlloc(nil, AllocSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  ArrayMem.RefCount:= 1;
  ArrayMem.Length:= AllocSize div SizeOf(Integer);
  a:= @ArrayMem.Elements;   //a:= AddressOf(elements)
  a[1]:= 10;        //testing, works
  a[0]:= 4;
  a[500000]:= 56;   //Works, autocommits, only adds a few k to the used memory
  button1.Caption:= IntToStr(a[500000]);  //displays '56'
end;

これはすべてうまくいきます。私の構造が 1.000.000 要素に成長した場合、すべてが機能します。
ただし、その後、構造が 1.000 要素に縮小したとします。

RAM を解放して、再度必要になったときに自動的にコミットされるようにするにはどうすればよいですか?

警告
David は、大きな (巨大な) 連続するメモリ ページをコミットすると大きなコストがかかると警告しました。
したがって、配列を小さなブロックに分割し、クラス/レコードを使用して内部を抽象化する方が有利な場合があります。

4

1 に答える 1

2

フラグをVirtualFree渡すことで、ページをデコミットできます。MEM_DECOMMITその後、 を使用して再度コミットできますVirtualAlloc

またはDiscardVirtualMemory、Windows 8.1 で導入された機能を使用することもできます。

この関数を使用して、メモリ領域自体をコミットしたまま、不要になったメモリ コンテンツを破棄します。メモリを破棄すると、システムに物理 RAM が返される場合があります。メモリの領域がアプリケーションによって再度アクセスされると、バッキング RAM が復元され、メモリの内容は未定義になります。

次の関連する質問へのコメントに役立つ情報が見つかるかもしれません:新しい Windows 8.1 API for virtual memory management: `DiscardVirtualMemory()` vs `VirtualAlloc()` and `MEM_RESET` and `MEM_RESET_UNDO`

于 2016-03-08T15:27:06.813 に答える