Какие бухгалтерские данные содержит динамический массив Delphi? - PullRequest
4 голосов
/ 15 декабря 2009

Вот простая программа для проверки выделения памяти. Проверка значений до и после с помощью диспетчера задач показывает, что каждый динамический массив занимает 20 байтов памяти при размере = 1. Размер элемента равен 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.

Ответы [ 3 ]

5 голосов
/ 15 декабря 2009

Я также посмотрел System.pas и заметил, что вызов GetMem в _DynArrayCopyRange поддерживает ваш анализ:

выделенный размер = количество * размер элемента + 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.

Это дает

  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

, который поддерживает 8-байтовую теорию служебных данных.

2 голосов
/ 15 декабря 2009

Распределения памяти имеют гранулярность, чтобы гарантировать, что все распределения выровнены Это просто помойка, вызванная этим.

0 голосов
/ 15 декабря 2009

Обновлен ... Я на самом деле пошел проверять код (что я должен был сделать раньше) и пришел к тому же выводу, что и Ульрих, он не хранит никакой информации о типе, только служебные данные Longint 2, а затем NbElements * ElementSize.
И диспетчер задач не является точным для такого рода мер.

С той странностью, что если вы измеряете память, используемую dynarray, она увеличивается нелинейно с размером элемента: для Записи с 2 или 3 целыми числами это тот же самый размер (20), с 4 или 5 это 28 ... после детализации размеров блоков.

Память измеряется с помощью:

// 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;
...