Pergunta

Aqui está um programa simples para verificar a alocação de memória. Verificar os valores antes e depois do gerenciador de tarefas sugere que cada matriz dinâmica ocupa 20 bytes de memória no tamanho = 1. O tamanho do elemento é 4, o que significa 16 bytes de sobrecarga para dados de contabilidade.

Ao procurar através do System.PAS, posso encontrar um campo de comprimento de matriz em -4 bytes e uma contagem de referência em -8 bytes, mas não consigo encontrar nenhuma referência ao outro 8. Alguém sabe o que faz?

Programa de amostra:

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.
Foi útil?

Solução

Também dei uma olhada no System.Pas e notei que a chamada getMem em _dyNarraycoPyRange suporta sua análise:

Tamanho alocado = contagem * Tamanho do elemento + 2 * tamanho de (longint)

. Então, talvez os números que você obtém do gerente de tarefas não sejam muito precisos. Você poderia tentar Pointer(someDynArray) := nil e verifique quais relatórios do FastMM de tamanho de vazamento de memória para números mais confiáveis.

Editar: Eu fiz um pequeno programa de teste:

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.

Isso rende

  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

que suporta a teoria das 8 bytes de 8 bytes.

Outras dicas

As alocações de memória têm granularidade para garantir que todas as alocações estejam alinhadas. Esta é apenas a inclinação causada por isso.

Atualizado ... Na verdade, fui verificar o código (o que eu deveria ter feito antes) e cheguei à mesma conclusão que a Ulrich, ele não está armazenando nenhuma informação de tipo, apenas as duas sobrecargas de longint e depois nBelEments*elementize.
E o gerente de tarefas não é preciso para esse tipo de medida.

Com a estranheza de que, se você medir a memória usada pelo Dynarray, aumenta não linearmente com o tamanho do elemento: para um registro com 2 ou 3 números inteiros, é do mesmo tamanho (20), com 4 ou 5 é 28 ... Após a granularidade dos bloqueios.

Memória medida com:

// 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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top