Какие бухгалтерские данные содержит динамический массив Delphi?
-
19-09-2019 - |
Вопрос
Вот простая программа для проверки распределения памяти. Проверка значений до и после менеджера задач предполагает, что каждый динамический массив занимает 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.
Решение
Я также посмотрел на систему. PAS и заметил, что вызов getMem в _dynarraycopyrange поддерживает ваш анализ:
выделенный размер = count * Размер элемента + 2 * sizeof (longint)
. Анкет Так что, возможно, цифры, которые вы получаете от Manager Task Manager, не очень точны. Вы могли бы попробовать 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 накладных расходах Longint, затем 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;