ما هي بيانات مسك الدفاتر التي تحتوي على صفيف ديناميكي دلفي؟

StackOverflow https://stackoverflow.com/questions/1903664

سؤال

إليك برنامج بسيط للتحقق من تخصيص الذاكرة. يوحي التحقق من قبل وبعد القيم مع مدير المهام أن كل صفيف ديناميكية تأخذ 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.
هل كانت مفيدة؟

المحلول

كان لدي نظرة في system.pas كذلك ولاحظت أن استدعاء GetMem في _dynarraycopyrange يدعم تحليلاتك:

حجم مخصص = عدد * حجم العنصر + 2 * Sizeof (Longr ...

. وبعد لذلك ربما الأرقام التي تحصل عليها من إدارة المهام ليست دقيقة للغاية. بامكانك ان تحاول 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.

هذه العوائد

 حدث تسرب الذاكرة غير المتوقع. تسرب الكتلة الصغيرة غير المتوقعة هي: 1 - 12 بايت: غير معروف X 1 13 - 20 بايت: غير معروف X 2 21 - 28 بايت: غير معروف X 2 29 - 36 بايت: غير معروف X 1

مما يدعم نظرية العلوية 8 البايت.

نصائح أخرى

مخصصات الذاكرة لها حبيبية لضمان محاذاة جميع المخصصات. هذا هو مجرد الجلاد الناجم عن هذا.

تحديث ... لقد ذهبت فعلا للتحقق من الكود (الذي يجب أن أفعله من قبل) وتوصل إلى نفس الاستنتاج مثل Ulrich، وليس تخزين أي معلومات من النوع، فقط 2 نغمة النطاق النفقات العامة ثم nbelements * عن الإصدادات.
و، مدير المهام غير دقيق لهذا النوع من التدبير.

مع الغرابة أنه إذا قمت بقياس الذاكرة المستخدمة من قبل 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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top