What accounting data does the Delphi dynamic array contain?

Here is a simple program to check memory allocation. Checking the values ​​before and after using the task manager assumes that each dynamic array occupies 20 bytes of memory with size = 1. The element size is 4, which means 16 bytes of service data for accounting data.

From viewing through system.pas, I can find the field length field of the array at -4 bytes and the reference count at -8 bytes, but I cannot find links to others. 8. Does anyone know what they are doing?

Program Example:

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
source share
3 answers

I also looked through System.pas and noticed that calling GetMem in _DynArrayCopyRange supports your analysis:

highlighted size = count * element size + 2 * Size (Longint)

. Therefore, perhaps the numbers you get from the task manager are not very accurate. You can try Pointer(someDynArray) := nil and check what size of memory leak FastMM reports for more reliable numbers.

Edit: I made a small test program:

 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. 

This gives

  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 

which supports 8-byte utility theory.

+5
source

Memory allocations are granular to ensure that all allocations are aligned. This is just the detachment caused by this.

+2
source

Update ... I actually went to check the code (which I should have done earlier), and I came to the same conclusion as Ulrich, it does not store type information, but only 2 Longint overhead, and then NbElements * ElementSize .
And the task manager is not accurate for this kind of measure.

With the oddity that if you measure the memory used by a dinar, it does not increase linearly with the size of the element: for recording with 2 or 3 integers, it has the same size (20), with 4 or 5 of its 28 ... after the granularity of the blocks.

Memory measured with:

 // 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; 
0
source

All Articles