4

これは、メモリ割り当てをチェックする簡単なプログラムです。タスク マネージャーで前後の値を確認すると、各動的配列がサイズ = 1 で 20 バイトのメモリを占有することが示唆されます。要素のサイズは 4 であり、これはブックキーピング データの 16 バイトのオーバーヘッドを意味します。

system.pas を調べると、-4 バイトの配列長フィールドと -8 バイトの参照カウントを見つけることができますが、他の 8 への参照を見つけることができないようです。

サンプルプログラム:

program Project1;

{$APPTYPE CONSOLE}

type
   TDynArray = array of integer;
   TLotsOfArrays = array[1..1000000] of TDynArray;
   PLotsOfArrays = ^TLotsOfArrays;

procedure allocateArrays;
var
   arrays: PLotsOfArrays;
   i: integer;
begin
   new(arrays);
   for I := 1 to 1000000 do
      setLength(arrays^[i], 1);
end;

begin
  readln;
  allocateArrays;
  readln;
end.
4

3 に答える 3

5

System.pas も調べたところ、_DynArrayCopyRange の GetMem 呼び出しが分析をサポートしていることに気付きました。

割り当てられたサイズ = カウント * 要素サイズ + 2 * Sizeof(Longint)

. そのため、タスク マネージャーから取得した数値はあまり正確ではない可能性があります。Pointer(someDynArray) := nilより信頼性の高い数値について、FastMM が報告するメモリ リーク サイズを確認してみてください。

編集:私は小さなテストプログラムを行いました:

program DynArrayLeak;

{$APPTYPE CONSOLE}

uses
  SysUtils;

procedure Test;
var
  arr: array of Integer;
  i: Integer;
begin
  for i := 1 to 6 do
  begin
    SetLength(arr, i);
    Pointer(arr) := nil;
  end;
end;

begin
  ReportMemoryLeaksOnShutdown := True;
  Test;
end.

これにより、

  予期しないメモリ リークが発生しました。予期しない小さなブロック リークは次のとおりです。

  1~12バイト:不明×1
  13~20バイト:不明×2
  21~28バイト:不明×2
  29~36バイト:不明×1

これは、8 バイトのオーバーヘッド理論をサポートしています。

于 2009-12-14T23:04:20.070 に答える
2

メモリ割り当てには、すべての割り当てが確実に整列されるように細分性があります。これは、これによって引き起こされるスロープです。

于 2009-12-15T01:25:52.297 に答える
0

更新...私は実際にコードをチェックしに行きました(以前に行うべきでした)。そして、Ulrich と同じ結論に達しました。型情報は格納されておらず、2 つの倍長整数のオーバーヘッドと NbElements*ElementSize だけです。
そして、タスクマネージャーはこの種の測定には正確ではありません.

dynarray によって使用されるメモリを測定すると、要素のサイズに比例して増加するという奇妙な点があります。ブロックサイズの粒度に従います。

以下で測定されたメモリ:

// Return the total Memory used as reported by the Memory Manager
function MemoryUsed: Cardinal;
var
  MemMgrState: TMemoryManagerState;
  SmallBlockState: TSmallBlockTypeState;
begin
  GetMemoryManagerState(MemMgrState);
  Result := MemMgrState.TotalAllocatedMediumBlockSize + MemMgrState.TotalAllocatedLargeBlockSize;
  for SmallBlockState in MemMgrState.SmallBlockTypeStates do begin
      Result := Result + SmallBlockState.UseableBlockSize * SmallBlockState.AllocatedBlockCount;
  end;
end;
于 2009-12-14T22:23:24.957 に答える