في علوم الحاسب، يعتبر تسرب الذاكرة نوع من الاستهلاك غير المتعمد للذاكرة المؤقتة "ram" في الحاسوب، بواسطة برنامج حاسوب، حيث يفشل البرنامج في إفراغ الذاكرة بعد الانتهاء من استخدامها، ويرى بالمصطلح نوع من الخطأ المرح في التسمية، لأن الذاكرة لا تفقد بطبيعة الحال من الحاسوب، ولكنها تصبح مشغولة ويتم تجاهلها بسبب خطأ تقني في عمليات البرنامج المنطقية.[1][2][3]
وكما يشار بالأسفل، يوجد لتسرب الذاكرة العديد من الأعراض المتشابهة مع أعراض مشاكل أخرى، وعامة لا يمكن تحليل سبب تلك الاعراض إلا بواسطة مبرمج حاسوب لديه وسيلة لرؤية المصدر الكودي للبرنامج، ومع ذلك فأغلب الناس يسارعون إلى وصف أي زيادة غير مرغوبة في استخدام الذاكرة بتسرب للذاكرة، حتى ولو لم يكن ذلك دقيقا.
نتائج تسرب الذاكرة
يمكن لتسرب الذاكرة التقليل من أداء الحاسوب، عن طريق تقليل كمية الذاكرة المتوفرة للحاسوب لكي يعمل بكفاءة. فتوزيع الذاكرة هو أساسا مهمة من مهام نظام التشغيل، لذلك ينتج عن تسرب الذاكرة ارتفاع ملحوظ في الذاكرة المستخدمة بنظام التشغيل ككل، وليس فقط بواسطة البرنامج المخطئ، وأخيرا، في أسوأ الأحوال، يتم اشغال الكثير من الذاكرة المتوفره ويتوقف كل أو جزء من النظام أو الأجهزة عن العمل بشكل صحيح أو يسقط النظام ككل.
قد لا يكون تسرب الذاكرة خطيرا أو ملحوظا بالوسائل الطبيعية في أغلب الأحيان. في نظم التشغيل الحديثة، الذاكرة المشغولة بواسطة برنامج يتم إفراغها عندما يغلق البرنامج، وذلك يعني أن تسرب الذاكرة بسبب برنامج يعمل لوقت قصير نادرا ما يكون خطيرا.
الحالات حين يكون التسرب أكثر خطوره قد تتضمن:
- حين يترك البرنامج المخطئ يعمل، ويستهلك ذاكرة أكثر فأكثر مع مرور الوقت (مثل المهمات الخلفية، في خواديم الويب، ولكن أكثر في الأجهزة المضمنة والتي يمكن أن تترك تعمل لسنين عديدة «مثال: مسير»)
- حين يكون البرنامج قادرا على طلب ذاكرة (مثال: ذاكرة مشتركة (shared memory) لم يتم إفراغها، حتى وإن أغلق البرنامج.
- حين يحدث التسرب بسبب نظام التشغيل.
- حين تكون الذاكرة قليلة جدا، مثال: داخل نظام مضمن (embedded system) أو جهاز محمول.
مثال لشخص عادي
هذا المثال يهدف لتوضيح كيفية حدوث تسرب بالذاكرة، ونتائجه، بدون الحاجة إلى أي معرفة بعلم البرمجة. يرجى ملاحظة أن هذا مثال توضيحي.
البريمج في هذه الحالة هو جزء من برنامج بسيط جدا مصمم للتحكم في مصعد، هذا الجزء من البرنامج ينفذ حينما يدخل أي شخص المصعد ويضغط على زر طابق معين للصعود اليه.
حين يضغط على زر:
- احصل على بعض الذاكرة، والتي سوف تستخدم لتذكر رقم الطابق المراد الصعود اليه.
- أحفظ رقم الطابق في الذاكرة
- هل نحن بالفعل في الطابق المراد؟
- إذا كنا كذلك، ليس لدينا شيء لنفعله: انتهى
إذا لم يكن كذلك:
- انتظر حتى يغلق المصعد
- اذهب إلى الطابق المطلوب
- افرغ الذاكرة التي استخدمت في تذكر رقم الطابق
قد يبدو هذا البريمج بسيطا بشكل كاف، ولكنه لديه بالفعل تسرب ذاكرة، فلنعتبر أن المصعد كان في الطابق رقم 3، حين يتم الضغط على الزر 3، نحجز جزء من الذاكرة، ولا نعيده أبدا. وفي كل مرة يحدث كذلك، نسرب المزيد من الذاكرة.
لن يكون لذلك تأثير مباشر، فغالبا لا يضغط الناس على زر الدور الذين يوجدوا فيه بالفعل، وفي جميع الأحوال، يمكن أن يكون للمصعد الكثير من الذاكرة الفارغة فيحدث ذلك مئات أو آلاف المرات، لكن أخيرا سوف تنفد ذاكرة المصعد، قد يأخذ هذا شهورا أو سنينا، لذلك يمكن عدم اكتشاف الخطأ حتى تحت أدق الاختبارات.
قد تكون النتائج أيضا غير جيدة، فقد ينتهي الأمر بالمصعد إلى عدم الاستجابة لطلبات الصعود لأدوار أخرى، وإذا كان المصعد يحتاج إلى ذاكرة لفتح الباب أيضا، فقد يحبس شخصا ما بداخل المصعد، لأنه لا توجد ذاكرة كافيه ليتم فتح ذلك الباب.
لاحظ أن التسرب لا يمكن ان يستمر إلا إذا استمر البرنامج بالعمل، كمثال، إذا انقطع التيار الكهربي فجأة عن المصعد، عندها عندما يعود التيار ستكون الذاكرة فارغة تماما ومتوفرة من جديد، حينها سيكون على عملية التسرب البطيئة البدء من جديد.
هل هو تسرب بالذاكرة؟
لاحظ أن ارتفاع مساحة الذاكرة المستخدمة ليس بالضرورة دليل على تسرب بالذاكرة، فبعض البرامج قد تخزن كميات من المعلومات تتطور دائما في الذاكرة، (مثال: مثل في الذاكرة المخبأة cache). إذا أمكن تمدد الكاش بشكل كبير بحيث تسبب مشاكل، قد يكون ذلك بسبب خطأ تصميمي أو برمجي، ولكن ليس تسرب ذاكرة، حيث أن المعلومات المخزنة تظل مستخدمة بشكل ضئيل. وفي بعض الحلات الأخرى، قد يطلب برنامج مساحة كبيرة جدا من الذاكرة بدون سبب، وذلك لأن المبرمج قد اعتبر أن الذاكرة دائما كافية لعملية ما، كمثال، قد يبدأ برنامج معالجة صور بقراءة كل محتويات الصورة وتخزينها في الذاكرة، وهذا شيء لا يتماشى مع أي صورة كبيرة جدا تتجاوز مساحتها مساحة الذاكرة المتوفرة.
لتوضيح ذلك أكثر، فإن تسرب في الذاكرة ينتج عن نوع محدد من الأخطاء في الكود البرمجي، وبدون وسيلة لرؤية الكود البرمجي، لا يستطيع أي شخص سوى الجزم بأن السبب يمكن أن يكون تسربا بالذاكرة، ويكون من الأفضل استخدام مصطلح «زيادة مستمرة في استهلاك الذاكرة المستخدمة» حينما لا توجد معرفة بالسبب الحقيقي.
إن مصطلح «تسرب الذاكرة» هو مستسهل بعض الشيء وقد يتعلق به غير المبرمجين خاصة ويستخدموه في حالات للذاكرة ليس لها أي علاقة بتسرب الذاكرة.
مثال بسيط لذاكرة لا يمكن الوصول إليها في لغة سي
هنا بريمج بلغة سي يتعمد تسريب الذاكرة عن طريق فقد المؤشر للذاكرة الموزعة، ولأن البريمج يستمر في العمل دائما باستدعاء الوظيفة الناقصة في الكود، فبالنهاية سيتوقف البرنامج عن العمل عندما لا تتوفر مساحة بالذاكرة فارغة.
# include <stdio.h>
int f(void)
{
char* s;
s = (char *)malloc(50); /* get memory */
if (s==NULL) return 1; /* no memory available */
else
{ /* memory available */
return 0; /* memory leak - see note below */
}
/*
* Memory was available and pointed to by s، but not saved.
* After this function returns، the pointer is destroyed،
* and the allocated memory becomes unreachable
*
* to "fix" this code، you would add the statement "free(s)" to
* the else block before the "return 0" statement
*/
}
int main(void)
{
/* this is an infinite loop calling the above function */
while (1) f(); /* This function call will fail to malloc sooner or later */
return 0 ;
}
انظر أيضًا
مراجع