memory-management ماذا وأين هي مكدس وكومة؟




12 Answers

كومة:

  • تخزينها في ذاكرة الوصول العشوائي الكمبيوتر تماما مثل الكومة.
  • سوف تخرج المتغيرات التي يتم إنشاؤها في المكدس من النطاق ويتم إلغاء تخصيصها تلقائيًا.
  • أسرع بكثير من تخصيص بالمقارنة مع المتغيرات على كومة الذاكرة المؤقتة.
  • تم التنفيذ مع بنية بيانات مكدسة فعلية.
  • تخزين البيانات المحلية وعناوين الإرجاع المستخدمة في تمرير المعلمات.
  • يمكن أن يكون تجاوز سعة مكدس عند استخدام الكثير من بنية تخزين العناصر (غالباً من العودية لانهائية أو عميق جداً التخصيصات كبيرة جداً).
  • يمكن استخدام البيانات التي تم إنشاؤها على المكدس بدون مؤشرات.
  • يمكنك استخدام بنية تخزين العناصر إذا كنت تعرف بالضبط مقدار البيانات التي تحتاج إلى تخصيصها قبل تجميع الوقت وليست كبيرة جدًا.
  • عادةً ما يكون الحد الأقصى للحجم محددًا بالفعل عند بدء تشغيل البرنامج.

كومة:

  • تخزينها في ذاكرة الوصول العشوائي الكمبيوتر تماما مثل المكدس.
  • في C ++ ، يجب أن يتم إتلاف المتغيرات على الكومة يدوياً ولا تقع خارج نطاق. يتم تحرير البيانات مع delete أو delete[] أو free .
  • أبطأ لتخصيص بالمقارنة مع المتغيرات على المكدس.
  • تستخدم عند الطلب لتخصيص كتلة من البيانات لاستخدامها من قبل البرنامج.
  • يمكن أن يكون هناك تجزئة عندما يكون هناك الكثير من التوزيعات و deallocations.
  • في C ++ أو C ، سيتم الإشارة إلى البيانات التي تم إنشاؤها في كومة بواسطة مؤشرات وتخصيصها مع new أو malloc على التوالي.
  • يمكن أن يكون لديك حالات فشل في التخصيص إذا طلب تخصيص مساحة كبيرة جدًا من المخزن المؤقت.
  • يمكنك استخدام الكومة إذا كنت لا تعرف بالضبط مقدار البيانات التي ستحتاجها في وقت التشغيل أو إذا كنت بحاجة إلى تخصيص الكثير من البيانات.
  • مسؤولة عن تسرب الذاكرة.

مثال:

int foo()
{
  char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
  bool b = true; // Allocated on the stack.
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
memory-management language-agnostic stack heap

تشرح كتب لغة البرمجة أن أنواع القيم يتم إنشاؤها على المكدس ، وأنواع المراجع يتم إنشاؤها على كومة الذاكرة المؤقتة ، دون شرح ما هذين الأمرين. لم أقرأ شرحًا واضحًا لهذا. أنا أفهم ما هو كومة . لكن،

  • أين وماذا هم (جسديا في ذاكرة الكمبيوتر الحقيقي)؟
  • إلى أي مدى يتحكم فيها نظام التشغيل أو وقت تشغيل اللغة؟
  • ما هو نطاقها؟
  • ما الذي يحدد حجم كل واحد منهم؟
  • ما الذي يجعل المرء أسرع؟



(لقد نقلت هذه الإجابة من سؤال آخر كان أكثر أو أقل من هذا السؤال.)

إن الإجابة على سؤالك تتعلق بالتطبيق المحدد وقد تختلف من خلال المجمعين ومعماريات المعالج. ومع ذلك ، هنا هو تفسير مبسط.

  • كلا مكدس الذاكرة المؤقتة والكومة هي مناطق الذاكرة المخصصة من نظام التشغيل الأساسي (غالباً الذاكرة الظاهرية التي يتم تعيينها إلى الذاكرة الفعلية عند الطلب).
  • في بيئة متعددة مؤشرات الترابط سيكون لدى كل مؤشر تراص الخاصة به مستقلة تماماً ولكن سيتم مشاركة الكومة. يجب التحكم في الوصول المتزامن على كومة الذاكرة المؤقتة وهو غير ممكن في بنية تخزين العناصر.

الكومة

  • يحتوي الكومة على قائمة مرتبطة من الكتل المستخدمة والحرة. يتم استيفاء عمليات تخصيص جديدة على الكومة ( new أو malloc ) عن طريق إنشاء كتلة مناسبة من أحد الكتل الحرة. يتطلب هذا تحديث قائمة كتل على الكومة. يتم أيضًا تخزين معلومات التعريف هذه حول الكتل الموجودة على الكومة على كومة الذاكرة المؤقتة في كثير من الأحيان في منطقة صغيرة أمام كل كتلة.
  • كلما كبرت الكومة يتم تخصيص كتل جديدة غالباً من عناوين أقل باتجاه عناوين أعلى. وبالتالي يمكنك التفكير في كومة الذاكرة المؤقتة ككومة من كتل الذاكرة التي تنمو في حجم كما يتم تخصيص الذاكرة. إذا كانت الكومة صغيرة جدًا للتخصيص ، فغالباً ما يمكن زيادة الحجم من خلال الحصول على المزيد من الذاكرة من نظام التشغيل الأساسي.
  • قد يؤدي تخصيص العديد من الكتل الصغيرة وإلغاء تخصيصها إلى ظهور الكومة في حالة يوجد بها الكثير من الكتل الحرة الصغيرة المنتشرة بين الكتل المستخدمة. قد يفشل طلب تخصيص كتلة كبيرة نظرًا لعدم وجود أي من الكتل الحرة كبيرة بما يكفي لتلبية طلب التخصيص على الرغم من أن الحجم المجمع للكتل الحرة قد يكون كبيرًا بما يكفي. يدعى هذا تجزئة كومة الذاكرة المؤقتة .
  • عندما يتم إلغاء تخصيص الكتلة المتاخمة لكتلة حرة ، يمكن دمج الكتلة الحرة الجديدة مع الكتلة الحرة المجاورة لإنشاء كتلة حرة أكبر تقلل بشكل فعال من تجزئة الكومة.

المدخنة

  • غالباً ما تعمل المكدس بالترادف مع سجل خاص على وحدة المعالجة المركزية يسمى مؤشر مكدس الذاكرة المؤقتة . في البداية يشير مؤشر مكدس إلى أعلى المكدس (أعلى عنوان في بنية تخزين العناصر).
  • وحدة المعالجة المركزية لديها تعليمات خاصة لدفع القيم على المكدس وظهرها مرة أخرى من المكدس. تقوم كل دفعة بتخزين القيمة في الموقع الحالي لمؤشر الكدسة وتقليل مؤشر المكدس. يسترد البوب القيمة التي يشير إليها مؤشر المكدس ، ثم يزيد من مؤشر المكدس (لا يتم الخلط بينه وبين حقيقة أن إضافة قيمة إلى الرصة يقلل من مؤشر المكدس ويؤدي إلى إزالة قيمة إلى زيادة ذلك. تذكر أن بنية تخزين العناصر تتزايد إلى القاع). القيم المخزنة والتي تم استرجاعها هي قيم سجلات وحدة المعالجة المركزية.
  • عند استدعاء دالة تستخدم وحدة المعالجة المركزية (CPU) تعليمات خاصة تدفع مؤشر الإرشادات الحالي ، أي عنوان التعليمات البرمجية التي يتم تنفيذها على المكدس. ثم ينتقل CPU إلى الدالة بتعيين مؤشر التعليمات إلى عنوان الدالة تسمى. في وقت لاحق ، عندما ترجع الدالة ، يتم بروز مؤشر التعليمات القديم من المكدس ثم استئناف التنفيذ في التعليمات البرمجية بعد استدعاء الدالة.
  • عند إدخال دالة ، يتم تقليل مؤشر المكدس لتخصيص مساحة أكبر على المكدس للمتغيرات المحلية (التلقائية). إذا كان لدى الدالة متغير محلي واحد 32 بت أربعة بايت يتم تعيين جانباً على المكدس. عندما ترجع الدالة ، يتم نقل مؤشر المكدس إلى الخلف لتحرير المنطقة المخصصة.
  • إذا كانت إحدى الدالات تحتوي على معلمات ، فسيتم ضغطها على المكدس قبل استدعاء الوظيفة. بعد ذلك ، تستطيع التعليمة البرمجية الموجودة في الدالة التنقل بين الكدسة من مؤشر الكدسة الحالي لتحديد هذه القيم.
  • دالة التعشيش تستدعي العمل مثل السحر. ستقوم كل مكالمة جديدة بتخصيص معاملات الدوال ، وعنوان المرسل ، والمساحة للمتغيرات المحلية ، ويمكن تكديس سجلات التنشيط هذه للمكالمات المتداخلة وسوف تزيلها بالطريقة الصحيحة عندما تعود الدالات.
  • نظرًا لأن المكدس عبارة عن كتلة محدودة من الذاكرة ، يمكن أن يتسبب في تجاوز سعة مكدس بواسطة استدعاء العديد من الدالات المتداخلة و / أو تخصيص مساحة كبيرة جدًا للمتغيرات المحلية. في كثير من الأحيان يتم إعداد مساحة الذاكرة المستخدمة في بنية تخزين العناصر بطريقة بحيث تؤدي الكتابة تحت الجزء السفلي (أقل عنوان) من المكدس إلى تشغيل اعتراض أو استثناء في وحدة المعالجة المركزية. هذه الحالة الاستثنائية يمكن بعد ذلك أن يتم اكتشافها بواسطة وقت التشغيل وتحويلها إلى نوع من الاستثناء الفائض.

يمكن تخصيص دالة على الكومة بدلاً من كدسة؟

لا ، يتم تخصيص سجلات التنشيط للوظائف (مثل المتغيرات المحلية أو التلقائية) على المكدس الذي يتم استخدامه ليس فقط لتخزين هذه المتغيرات ، ولكن أيضًا لتتبع مكالمات الدالة المتداخلة.

كيفية إدارة كومة الذاكرة المؤقتة بالفعل إلى بيئة وقت التشغيل. يستخدم C malloc و C ++ new ، ولكن العديد من اللغات الأخرى تحتوي على تجميع البيانات المهملة.

ومع ذلك ، فإن المكدس عبارة عن ميزة ذات مستوى منخفض مرتبطة ارتباطًا وثيقًا ببنية المعالج. لا تكون زيادة حجم الكومة عند عدم وجود مساحة كافية أمرًا صعبًا نظرًا لأنه يمكن تنفيذها في استدعاء المكتبة الذي يتعامل مع الكومة. ومع ذلك ، غالباً ما يكون من المستحيل زيادة بنية تخزين العناصر في حالة اكتشاف تجاوز سعة التكديس فقط عند فوات الأوان ؛ وإغلاق موضوع التنفيذ هو الخيار الوحيد القابل للتطبيق.




المكدس عند استدعاء دالة ، يتم وضع الوسيطات إلى هذه الوظيفة بالإضافة إلى بعض الحمولة الأخرى على المكدس. يتم تخزين بعض المعلومات (مثل أين تذهب في العودة) هناك أيضا. عندما تقوم بتعريف متغير داخل وظيفتك ، يتم تخصيص هذا المتغير أيضًا على المكدس.

إلغاء تخصيص المكدس بسيط جدًا لأنك دائمًا تنقح في الترتيب العكسي الذي تقوم بتخصيصه. تتم إضافة أشياء مكدس أثناء إدخال الوظائف ، تتم إزالة البيانات المقابلة أثناء الخروج منها. هذا يعني أنك تميل إلى البقاء داخل منطقة صغيرة من المكدس ما لم تستدعي الكثير من الوظائف التي تستدعي الكثير من الوظائف الأخرى (أو تنشئ حلاً متكرراً).

The Heap الكومة هي اسم عام حيث تضع البيانات التي تقوم بإنشائها على الطاير. إذا كنت لا تعرف عدد سفن الفضاء التي سيقوم برنامجك بإنشائها ، فمن المحتمل أن تستخدم المشغل الجديد (أو malloc أو المكافئ) لإنشاء كل سفينة فضائية. سوف يستمر هذا التخصيص لفترة من الوقت ، لذا من المحتمل أن نحرر الأشياء بترتيب مختلف عن الذي أنشأناها.

وبالتالي ، فإن الكومة هي أكثر تعقيدًا ، لأن هناك في نهاية المطاف مناطق من الذاكرة غير مستخدمة متداخلة مع قطع - يتم تجزئة الذاكرة. العثور على ذاكرة حرة بالحجم الذي تحتاجه هو مشكلة صعبة. هذا السبب يجب تجنب كومة الذاكرة المؤقتة (على الرغم من أنه لا يزال يتم استخدامها غالباً).

تنفيذ تطبيق كلاً من المكدس و كومة الذاكرة المؤقتة عادةً إلى وقت التشغيل / نظام التشغيل. غالباً ما تقوم الألعاب والتطبيقات الأخرى ذات الأداء الفائق بإنشاء حلول الذاكرة الخاصة بها التي تلتقط جزءًا كبيرًا من الذاكرة من الكومة ثم تفرغها داخليًا لتجنب الاعتماد على نظام التشغيل للذاكرة.

هذا أمر عملي فقط إذا كان استخدامك للذاكرة مختلفًا تمامًا عن المعيار - أي للألعاب التي يتم فيها تحميل مستوى في عملية ضخمة واحدة ويمكنها أن تشق الجزء الأكبر في عملية ضخمة أخرى.

الموقع المادي في الذاكرة هذا أقل أهمية مما تعتقد بسبب تقنية تسمى Virtual Memory مما يجعل برنامجك يعتقد أنك تستطيع الوصول إلى عنوان معين حيث تكون البيانات الفعلية في مكان آخر (حتى على القرص الصلب!). تكون العناوين التي تحصل عليها للتكدس في تزايد مستمر مع تعمق شجرة الاتصال الخاصة بك. لا يمكن التنبؤ بعناوين كومة الذاكرة المؤقتة (بمعنى أنها محددة بدقة) وبصراحة ليست مهمة.




وقد أجاب آخرون على السكتات الدماغية واسعة بشكل جيد ، لذلك أنا رمي في بعض التفاصيل.

  1. لا يلزم أن تكون المكدس والكومة مفردة. هو الوضع الشائع الذي يكون لديك أكثر من رصة واحدة إذا كان لديك أكثر من سلسلة واحدة في عملية ما. في هذه الحالة ، يحتوي كل مؤشر ترابط. كما يمكن أن يكون لديك أكثر من كومة واحدة ، على سبيل المثال ، يمكن أن تؤدي بعض تكوينات DLL إلى ملفات DLL مختلفة يتم تخصيصها من أكوام مختلفة ، وهذا هو السبب في أنها فكرة سيئة بشكل عام لتحرير الذاكرة المخصصة لمكتبة مختلفة.

  2. في C يمكنك الحصول على فائدة من تخصيص طول متغير من خلال استخدام alloca ، الذي يخصص على المكدس، في مقابل الوك، الذي يخصص على الكومة. لن تنجو هذه الذاكرة من بيان الإرجاع ، ولكنها مفيدة لمخزن المؤقت.

  3. إن إنشاء مخزن مؤقت ضخم على Windows لا تستخدمه كثيرًا ليس مجانيًا. هذا لأن المحول البرمجي سيقوم بإنشاء حلقة اختبار مكدس يتم استدعائها في كل مرة يتم إدخال الدالة الخاصة بك للتأكد من وجود المكدس (لأن Windows يستخدم صفحة حماية واحدة في نهاية مجموع المكدس الخاص بك للكشف عن الوقت الذي يحتاج فيه إلى زيادة بنية تخزين العناصر. إذا قمت بالوصول إلى الذاكرة أكثر من صفحة واحدة خارج نهاية المكدس سوف تعطل). مثال:

void myfunction()
{
   char big[10000000];
   // Do something that only uses for first 1K of big 99% of the time.
}



المكدس عبارة عن جزء من الذاكرة يمكن التلاعب به عبر عدة تعليمات لغة التجميع الرئيسية ، مثل 'pop' (إزالة وإرجاع قيمة من المكدس) و "push" (دفع قيمة إلى المكدس) ، ولكن أيضًا استدعاء ( استدعاء روتين - هذا يدفع العنوان للعودة إلى المكدس) والعودة (العودة من روتين فرعي - هذا الملوثات العضوية الثابتة عنوان المكدس ويقفز إليه). إنها منطقة الذاكرة أسفل سجل مؤشر المكدس ، والتي يمكن ضبطها حسب الحاجة. يتم استخدام المكدس أيضاً لتمرير الوسائط إلى subroutines وكذلك للحفاظ على القيم في السجلات قبل استدعاء subroutines.

الكومة هي جزء من الذاكرة يتم إعطاؤه للتطبيق بواسطة نظام التشغيل ، عادةً عبر syscall مثل malloc. على أنظمة تشغيل حديثة هذه الذاكرة عبارة عن مجموعة من الصفحات التي يمكن الوصول إليها فقط في عملية الاستدعاء.

يتم تحديد حجم الحزمة في وقت التشغيل ، ولا تنمو بشكل عام بعد إطلاق البرنامج. في برنامج C ، يجب أن تكون المكدس كبيرة بما يكفي لاحتواء كل متغير يتم الإعلان عنه داخل كل دالة. ستنمو الكومة بشكل ديناميكي حسب الحاجة ، لكن نظام التشغيل يقوم بإجراء المكالمة في النهاية (سيؤدي ذلك إلى نمو الكومة بأكثر من القيمة المطلوبة من malloc ، بحيث لا يحتاج بعض mallocs المستقبل على الأقل للعودة إلى kernel الحصول على المزيد من الذاكرة ، وهذا السلوك قابل للتخصيص في كثير من الأحيان)

نظرًا لأنك قد قمت بتخصيص الرصة قبل إطلاق البرنامج ، فإنك لن تحتاج أبداً إلى malloc قبل أن تتمكن من استخدام المكدس ، لذلك فهناك ميزة بسيطة هناك. من الناحية العملية ، من الصعب جدًا التنبؤ بما سيكون سريعًا وما سيكون بطيئًا في أنظمة التشغيل الحديثة التي تحتوي على أنظمة فرعية للذاكرة الظاهرية ، لأن كيفية تنفيذ الصفحات ومكان تخزينها هي تفاصيل التنفيذ.




ما هو كومة؟

الكومة هي كومة من الكائنات ، عادة ما تكون مرتبة مرتبة بدقة.

الأكوام في معماريات الحوسبة هي مناطق من الذاكرة حيث تتم إضافة البيانات أو إزالتها بطريقة أخيرة في الخارج.
في تطبيق متعدد مؤشرات الترابط ، سيكون لكل مؤشر ترابط الخاص به.

ما هو كومة؟

الكومة هي مجموعة غير مرتبة من الأشياء تتكدس بشكل عشوائي.

في بنية الحوسبة ، يكون الكومة منطقة من الذاكرة المخصصة ديناميكيًا يتم إدارتها تلقائيًا بواسطة نظام التشغيل أو مكتبة مدير الذاكرة.
يتم تخصيص الذاكرة على الكومة ، إلغاء تخصيصها ، وتغيير حجمها بانتظام أثناء تنفيذ البرنامج ، وهذا يمكن أن يؤدي إلى مشكلة تسمى التجزئة.
يحدث التفتت عند تخصيص كائنات الذاكرة بمسافات صغيرة بين صغيرة جدًا لا يمكن تخزينها على كائنات ذاكرة إضافية.
النتيجة الصافية هي نسبة مئوية من مساحة الكومة غير قابلة للاستخدام لمزيد من عمليات تخصيص الذاكرة.

الاثنين معا

في تطبيق متعدد مؤشرات الترابط ، سيكون لكل مؤشر ترابط الخاص به. ولكن ، ستشارك جميع الخيوط المختلفة في الكومة.
لأن مؤشرات الترابط المختلفة مشاركة كومة الذاكرة المؤقتة في تطبيق متعدد مؤشرات الترابط ، وهذا يعني أيضاً أن هناك بعض التنسيق بين مؤشرات الترابط بحيث لا يحاول الوصول إلى نفس قطعة (أجزاء) الذاكرة في كومة الذاكرة المؤقتة في نفس الوقت.

أيهما أسرع - المكدس أو كومة الذاكرة المؤقتة؟ و لماذا؟

المكدس هو أسرع بكثير من كومة الذاكرة المؤقتة.
هذا بسبب الطريقة التي يتم تخصيص الذاكرة على المكدس.
تخصيص الذاكرة على المكدس بسيطة مثل نقل مؤشر المكدس لأعلى.

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

نموذج ذاكرة جافا

المكدس هو مساحة الذاكرة حيث يتم تخزين المتغيرات المحلية (بما في ذلك معلمات الأسلوب). عندما يتعلق الأمر بمتغيرات الكائن ، هذه مجرد مراجع (مؤشرات) إلى الكائنات الفعلية على الكومة.
في كل مرة يتم فيها إنشاء كائن ، يتم تعيين جزء من ذاكرة الكومة جانباً للاحتفاظ ببيانات (حالة) ذلك الكائن. نظرًا لأن الكائنات يمكن أن تحتوي على كائنات أخرى ، فإن بعض هذه البيانات يمكنها في الواقع الاحتفاظ بمراجع لتلك الكائنات المتداخلة.




ببساطة ، المكدس هو حيث يتم إنشاء المتغيرات المحلية. أيضاً ، في كل مرة تقوم فيها باستدعاء روتين فرعي برنامج (مؤشر إلى تعليمة الجهاز التالي) وأي سجلات هامة ، وأحياناً يتم دفع المعلمات على المكدس. ثم يتم دفع أي المتغيرات المحلية داخل الروتين الفرعي في المكدس (واستخدامها من هناك). عندما ينتهي الروتين الفرعى ، تنبثق كل تلك الأشياء من الكومة. يحصل على جهاز الكمبيوتر وتسجيل البيانات مرة أخرى حيث تم برزت ، لذلك يمكن للبرنامج الخاص بك يذهب على طريقه مرح.

كومة الذاكرة المؤقتة هي منطقة من عمليات تخصيص الذاكرة الحيوية للذاكرة مصنوعة من (المكالمات "الجديدة" أو "المخصصة" الواضحة). وهو عبارة عن بنية بيانات خاصة يمكنها تتبع كتل الذاكرة ذات الأحجام المختلفة وحالة تخصيصها.

في الأنظمة "الكلاسيكية" تم وضع ذاكرة الوصول العشوائي بحيث بدأ مؤشر المكدس في الجزء السفلي من الذاكرة ، بدأ مؤشر كومة في الأعلى ، ونمت نحو بعضها البعض. إذا تداخلت ، فأنت خارج ذاكرة الوصول العشوائي. هذا لا يعمل مع أنظمة تشغيل متعددة الخيوط الحديثة بالرغم من ذلك. يجب أن يكون لكل مؤشر ترابط خاص به ، ويمكن إنشاء تلك الصفحات ديناميكيًا.




كومة

  • وصول سريع جدا
  • لا تضطر إلى إلغاء تخصيص المتغيرات بشكل صريح
  • تتم إدارة المساحة بكفاءة بواسطة وحدة المعالجة المركزية (CPU) ، لن تصبح الذاكرة مجزأة
  • المتغيرات المحلية فقط
  • الحد على حجم الرصة (معتمد على نظام التشغيل)
  • لا يمكن تغيير حجم المتغيرات

كومة

  • يمكن الوصول إلى المتغيرات على مستوى العالم
  • لا يوجد حد لحجم الذاكرة
  • (نسبيا) الوصول أبطأ
  • لا يوجد استخدام مضمون فعال للمساحة ، فقد تصبح الذاكرة مجزأة مع مرور الوقت حيث يتم تخصيص كتل الذاكرة ، ثم يتم تحريرها
  • يجب عليك إدارة الذاكرة (أنت مسؤول عن تخصيص وتحرير المتغيرات)
  • يمكن تغيير حجم المتغيرات باستخدام realloc ()



  • المقدمة

الذاكرة الفيزيائية هي نطاق العناوين المادية لخلايا الذاكرة التي يخزن فيها التطبيق أو النظام بياناته ورمزه وما إلى ذلك أثناء التنفيذ. تشير إدارة الذاكرة إلى إدارة هذه العناوين الفعلية من خلال تبديل البيانات من الذاكرة الفعلية إلى جهاز تخزين ثم العودة إلى الذاكرة الفعلية عند الحاجة. يقوم نظام التشغيل بتنفيذ خدمات إدارة الذاكرة باستخدام الذاكرة الظاهرية. باعتبارك مطور تطبيقات C # لا تحتاج إلى كتابة أي خدمات إدارة للذاكرة. يستخدم CLR خدمات إدارة ذاكرة نظام التشغيل الأساسية لتوفير نموذج الذاكرة لـ C # أو أي لغة أخرى عالية المستوى تستهدف CLR.

يوضح الشكل 4-1 الذاكرة الفعلية التي تم استخراجها وإدارتها بواسطة نظام التشغيل ، باستخدام مفهوم الذاكرة الظاهرية. الذاكرة الظاهرية هي النظرة المجردة للذاكرة الفعلية ، التي يديرها نظام التشغيل. الذاكرة الظاهرية هي ببساطة سلسلة من العناوين الافتراضية ، ويتم ترجمة هذه العناوين الظاهرية من قبل وحدة المعالجة المركزية إلى العنوان الفعلي عند الحاجة.

الشكل 4-1. تجريد الذاكرة CLR

يوفر CLR طبقة تجريدية لإدارة الذاكرة لبيئة التشغيل الافتراضية ، باستخدام خدمات الذاكرة العاملة. تستخدم المفاهيم المستخلصة التي يستخدمها CLR AppDomain ، و thread ، و stack ، و heapmemorymapped الملف ، وما إلى ذلك. يمنح مفهوم المجال التطبيق (AppDomain) التطبيق الخاص بك بيئة تنفيذ معزولة.

  • تفاعل الذاكرة بين CLR و OS

من خلال النظر إلى تتبع المكدس أثناء تصحيح تطبيق C # التالي ، باستخدام WinDbg ، سترى كيف يستخدم CLR خدمات إدارة ذاكرة نظام التشغيل الأساسية (على سبيل المثال ، أسلوب HeapFree من KERNEL32.dll ، أسلوب RtlpFreeHeap من ntdll.dll) لتنفيذ نموذج الذاكرة الخاصة به:

using System;
namespace CH_04
{
    class Program
    {
        static void Main(string[] args)
        {
            Book book = new Book();
            Console.ReadLine();
        }
    }

    public class Book
    {
        public void Print() { Console.WriteLine(ToString()); }
    }
}

يتم تحميل التجميع المترجمة للبرنامج في WinDbg لبدء التصحيح. يمكنك استخدام الأوامر التالية لتهيئة جلسة عمل التصحيح:

0: 000> sxe ld clrjit

0: 000> g

0: 000> .loadby sos clr

0: 000> .load C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ sos.dll

ثم قمت بتعيين نقطة توقف في الأسلوب الرئيسي لفئة البرنامج ، باستخدام الأمر! bpmd:

0: 000>! bpmd CH_04.exe CH_04.Program.Main

لمتابعة التنفيذ والفاصل عند نقطة الإيقاف ، قم بتنفيذ الأمر g:

0: 000> g

عندما ينفصل التنفيذ عند نقطة الإيقاف ، يمكنك استخدام الأمر! eestack لعرض تفاصيل تتبع المكدس لكل سلاسل العمليات قيد التشغيل في العملية الحالية. يعرض الإخراج التالي تتبع مكدس كافة مؤشرات الترابط قيد التشغيل التطبيق CH_04.exe:

0: 000>! eestack

الموضوع 0

الإطار الحالي: (MethodDesc 00233800 +0 CH_04.Program.Main (System.String []))

ChildEBP RetAddr المتصل ، كالي

0022ed24 5faf21db clr! CallDescrWorker + 0x33

/ أثر إزالتها /

0022f218 77712d68 ntdll! RtlFreeHeap + 0x142 ، الاتصال ntdll! RtlpFreeHeap

0022f238 771df1ac KERNEL32! HeapFree + 0x14 ، الاتصال بـ ntdll! RtlFreeHeap

0022f24c 5fb4c036 clr! EEHeapFree + 0x36، call KERNEL32! HeapFree

0022f260 5fb4c09d clr! EEHeapFreeInProcessHeap + 0x24، call clr! EEHeapFree

0022f274 5fb4c06d clr! حذف المشغل [] + 0x30 ، استدعاء clr! EEHeapFreeInProcessHeap / trace removed /

0022f4d0 7771316f ntdll! RtlpFreeHeap + 0xb7a ، الاتصال بـ ntdll! _SEH_epilog4

0022f4d4 77712d68 ntdll! RtlFreeHeap + 0x142 ، استدعاء ntdll! RtlpFreeHeap

0022f4f4 771df1ac KERNEL32! HeapFree + 0x14 ، الاتصال بـ ntdll! RtlFreeHeap

/ أثر إزالتها /

يشير تتبع الكدسة هذا إلى أن CLR تستخدم خدمات إدارة نظام تشغيل OS لتطبيق نموذج الذاكرة الخاص بها. أي عملية نقل للذاكرة في NET يتم تمريرها عبر طبقة الذاكرة CLR إلى طبقة إدارة ذاكرة نظام التشغيل.

يوضح الشكل 4-2 نموذج ذاكرة نموذج C # نموذجي يستخدمه CLR في وقت التشغيل.

الشكل 4-2 . نموذج ذاكرة نموذج C # نموذجي

يقترن نموذج ذاكرة CLR بإحكام مع خدمات إدارة ذاكرة نظام التشغيل. لفهم نموذج ذاكرة CLR ، من المهم فهم نموذج ذاكرة نظام التشغيل الأساسي. من المهم أيضًا معرفة كيف يتم تلخيص مساحة عنوان الذاكرة الفعلية في مساحة عنوان الذاكرة الظاهرية ، والطرق التي يتم بها استخدام مساحة العنوان الظاهرية من قبل تطبيق المستخدم وتطبيق النظام ، وكيفية عمل خرائط العناوين الظاهرية إلى الفعلية ، وكيفية الذاكرة يعمل ملف معين ، وهلم جرا. ستعمل هذه المعرفة في الخلفية على تحسين فهمك لمفاهيم طراز ذاكرة CLR ، بما في ذلك AppDomain و stack و heap.

لمزيد من المعلومات ، يرجى الرجوع إلى هذا الكتاب:

C # Deconstructed: اكتشف كيف يعمل C # على .NET Framework

هذا الكتاب + ClrViaC # + Windows Internals هي موارد ممتازة لمعرفة إطار .net في العمق والعلاقة مع نظام التشغيل.




OK، ببساطة وبعبارة قصيرة، فإنها تعني أمر و لم يؤمر ...!

المكدس : في العناصر المكدس ، تحصل الأشياء على الجزء العلوي من بعضها البعض ، يعني أن تكون أسرع وأكثر كفاءة لتتم معالجتها! ...

لذلك هناك دائمًا مؤشر يشير إلى العنصر المحدد ، وستكون المعالجة أيضًا أسرع ، وهناك علاقة بين العناصر أيضًا! ...

الكومة : لا يوجد ترتيب ، وستكون المعالجة أبطأ والقيم معطلة مع عدم وجود طلب أو مؤشر محدد ... هناك عشوائي وليس هناك علاقة بينهما ... لذلك يمكن أن يختلف التنفيذ ووقت الاستخدام ...

أقوم أيضًا بإنشاء الصورة أدناه لإظهار كيف يمكن أن تبدو:




كومة ، كومة و البيانات لكل عملية في الذاكرة الظاهرية:




لدي شيء أشاركه معك ، على الرغم من أن النقاط الرئيسية قد تم كتابتها بالفعل.

كومة

  • وصول سريع جدا.
  • تخزينها في ذاكرة الوصول العشوائي.
  • يتم تحميل مكالمات الدالة هنا جنبا إلى جنب مع المتغيرات المحلية والمعلمات الدالة التي تم تمريرها.
  • يتم تحرير مساحة تلقائيا عندما يخرج البرنامج من نطاق.
  • مخزنة في الذاكرة المتسلسلة.

كومة

  • الوصول البطيء نسبياً إلى المكدس.
  • تخزينها في ذاكرة الوصول العشوائي.
  • يتم تخزين المتغيرات التي تم إنشاؤها ديناميكيًا هنا ، والتي تتطلب لاحقًا تحرير الذاكرة المخصصة بعد الاستخدام.
  • مخزنة في أي مكان يتم فيه تخصيص الذاكرة ، يتم الوصول إليها بواسطة المؤشر دائمًا.

ملاحظة مثيرة للاهتمام:

  • إذا كان قد تم تخزين مكالمات الدالة في كومة الذاكرة المؤقتة ، فقد يؤدي ذلك إلى نقطتي فوضى:
    1. نظرًا للتخزين المتسلسل في الرصة ، يكون التنفيذ أسرع. كان من الممكن أن يؤدي التخزين في الكومة إلى استهلاك ضخم للوقت مما أدى إلى تنفيذ البرنامج بأكمله بشكل أبطأ.
    2. إذا تم تخزين الدالات في كومة الذاكرة المؤقتة (التخزين الفوضوي المشار إليه بواسطة مؤشر) ، لن تكون هناك أية طريقة للعودة إلى عنوان المتصل مرة أخرى (والذي يعطي المكدس بسبب التخزين المتسلسل في الذاكرة).

هي wellcomed الاحصائيات.






Related