تسرب الذاكرة

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

مثال لشخص عادي

هذا المثال يهدف لتوضيح كيفية حدوث تسرب بالذاكره، ونتائجه، بدون الحاجة إلى اي معرفه بعلم البرمجه. يرجى ملاحظة ان هذا مثال توضيحي.
البريمج في هذه الحالة هو جزء من برنامج بسيط جدا مصمم للتحكم في مصعد، هذا الجزء من البرنامج ينفذ حينما يدخل أي شخص المصعد ويضغط على زر طابق معين للصعود اليه.
حين يضغط على زر:
   احصل على بعض الذاكرة، والتي سوف تستخدم لتذكر رقم الطابق المراد الصعود اليه.
   أحفظ رقم الطابق في الذاكرة
   هل نحن بالفعل في الطابق المراد؟
   إذا كنا كذلك، ليس لدينا شيء لنفعله: انتهى
   إذا لم يكن كذلك:
        انتظر حتى يغلق المصعد
        اذهب إلى الطابق المطلوب
        افرغ الذاكرة التي استخدمت في تذكر رقم الطابق
قد يبدو هذا البريمج بسيطا بشكل كاف، ولكنه لديه بالفعل تسرب ذاكره، فلنعتبر ان المصعد كان في الطابق رقم 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 ; 
}