Frage

Hier ist ein einfaches Programm zur Überprüfung der Speicherzuweisung. Das Überprüfen vor und nach den Werten mit Task Manager schlägt vor, dass jedes dynamische Array 20 Bytes Speicher bei Größe = 1. Die Elementgröße beträgt 4, was 16 Bytes Overhead für Buchhaltungsdaten bedeutet.

Von system.pas kann ich ein Arraylängefeld in -4 Bytes und eine Referenzzahl bei -8 Bytes finden, aber ich kann anscheinend keine Hinweise auf die anderen 8 finden. Hat jemand, was er tut?

Beispielprogramm:

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.
War es hilfreich?

Lösung

Ich habe auch ein Blick auf System.pas geworfen und festgestellt, dass der GetMem -Anruf in _dynarrayCopyrange Ihre Analyis unterstützt:

zugewiesene Größe = Anzahl * Elementgröße + 2 * Größe (Longint)

. Vielleicht sind die Zahlen, die Sie vom Task -Manager erhalten, nicht sehr genau. Du könntest es versuchen Pointer(someDynArray) := nil und prüfen Sie, welche Speicherleckgröße Fastmm -Berichte für zuverlässigere Zahlen berichtet.

Bearbeiten: Ich habe ein kleines Testprogramm gemacht:

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.

Dies ergibt

  An unexpected memory leak has occurred. The unexpected small block leaks are:

  1 - 12 bytes: Unknown x 1
  13 - 20 bytes: Unknown x 2
  21 - 28 bytes: Unknown x 2
  29 - 36 bytes: Unknown x 1

Das unterstützt die 8 -Byte -Overwadtheorie.

Andere Tipps

Speicherzuweisungen haben Granularität, um sicherzustellen, dass alle Zuteilungen ausgerichtet sind. Dies ist nur der dadurch verursachte Slop.

Aktualisiert ... Ich habe den Code (den ich schon einmal hätte tun sollen) und bin zu dem gleichen Schluss wie Ulrich gekommen. Es speichert keine Informationen, nur den 2 Longint -Overhead, dann die Elemente.
Und Task Manager ist für diese Art von Maß nicht korrekt.

Mit der Kuriosität, dass, wenn Sie das von der Dynarray verwendete Speicher messen, nicht linear mit der Größe des Elements erhöht: Für einen Datensatz mit 2 oder 3 Ganzzahlen ist es die gleiche Größe (20), mit 4 oder 5 ist es 28 ... folgt der Granularität des Blocks.

Speicher gemessen mit:

// 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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top