0Pricing
C Academy · درس

اكتشاف التسربات

أساسيات memcheck

اكتشاف التسربات درس مجاني في C Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C Academy 4 دروس في المجموع.

ما هو التسرّب

يحدث تسرّب الذاكرة عندما تخصص ذاكرة من الكومة باستخدام malloc أو calloc أو realloc ثم تفقد كل مؤشر إليها قبل استدعاء free.

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

تسرّب بسيط

يسرّب هذا البرنامج كتلة واحدة حجمها 40 بايتًا.

المؤشر p متغير محلي. وعند عودة main يختفي p، لكن كتلة الكومة التي كان يشير إليها لا تُحرَّر أبدًا.

#include <stdlib.h>

int main(void) {
    int *p = malloc(10 * sizeof(int));
    p[0] = 1;
    return 0; /* never free(p) */
}

تشغيل memcheck

أداة memcheck هي الأداة الافتراضية، لذا يمكنك حذف اسم الأداة.

أضف --leak-check=full للحصول على تتبع للمكدس لكل تخصيص متسرّب.

gcc -g -O0 -o leak leak.c
valgrind --leak-check=full ./leak

ملخص التسرّبات

عند الخروج، تطبع Valgrind ملخصًا للتسرّبات بعنوان LEAK SUMMARY. وبالنسبة إلى البرنامج السابق، سيظهر تقريبًا كما يلي:

definitely lost: 40 bytes in 1 blocks

يشير التتبع إلى موضع استدعاء malloc بالضبط، وبذلك تعرف تحديدًا أي تخصيص لم يُحرَّر.

فئات التسرّب الأربع

تصنّف memcheck الذاكرة المفقودة ضمن أربع فئات:

  • definitely lost — لم يبقَ أي مؤشر؛ وهذا تسرّب حقيقي
  • indirectly lost — لا يمكن الوصول إليها إلا عبر كتلة مفقودة حتمًا
  • possibly lost — لم يبقَ سوى مؤشر داخلي
  • still reachable — يوجد مؤشر عند الخروج، لكنك لم تحرر الذاكرة

الفرق بين Definitely lost وStill reachable

الفئة definitely lost هي العاجلة: فلا يمكن استعادة تلك البايتات ما دامت العملية قيد التشغيل.

أما still reachable فهي أقل خطورة. تكون الكتلة متسرّبة عند الخروج، لكن مؤشرًا عامًا أو ثابتًا لا يزال يشير إليها؛ لذا تكون عادةً تخصيصًا يُجرى مرة واحدة ولم تكلف نفسك تحريره.

التسرّبات غير المباشرة

عندما تفقد رأس بنية مترابطة، يصبح كل عنصر فيها غير قابل للوصول.

يظهر الرأس على أنه definitely lost، وتظهر بقية العناصر على أنها indirectly lost. ويؤدي إصلاح السبب الجذري، أي فقدان الرأس، إلى استعادة الكل.

struct Node { int v; struct Node *next; };

struct Node *make(void) {
    struct Node *h = malloc(sizeof *h);
    h->next = malloc(sizeof *h);
    h->next->next = NULL;
    return h;
}
/* if the caller drops the returned head, both nodes leak */

الإصدار المُصلح

حرّر ما تخصصه. هذا الإصدار لا يسرّب شيئًا.

تُظهر Valgrind عند تشغيله الرسالة All heap blocks were freed -- no leaks are possible.

#include <stdlib.h>

int main(void) {
    int *p = malloc(10 * sizeof(int));
    p[0] = 1;
    free(p);
    return 0;
}

عدّ التخصيصات

حتى من دون وجود تسرّبات، يخبرك HEAP SUMMARY بمدى انشغال برنامجك:

total heap usage: 1 allocs, 1 frees, 40 bytes allocated

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

إظهار الكتل القابلة للوصول

لا تسرد memcheck افتراضيًا تفاصيل الكتل still reachable. ولتدقيق هذه الكتل أيضًا، أضف:

--show-leak-kinds=all

يفرض ذلك عرض تتبع لكل فئة، وهو مفيد عندما تريد برنامجًا يحرر كل شيء تمامًا قبل الخروج.

valgrind --leak-check=full --show-leak-kinds=all ./leak

التسرّبات في مسارات الأخطاء

تختبئ أكثر التسرّبات مراوغة في مسارات العودة المبكرة. في هذه الحالة، إذا فشل التخصيص الثاني، تتسرّب الكتلة الأولى.

نادرًا ما تصل الاختبارات العادية إلى هذه الفروع، لكن memcheck تكتشفها كلما نُفّذ المسار. احرص دائمًا على تحرير ما تملكه قبل العودة بسبب خطأ.

char *a = malloc(100);
char *b = malloc(100);
if (!b) {
    /* bug: a is leaked here */
    return -1;
}
/* fix: free(a); before returning */

تحقق سريع

اختر فئة التسرّب التي تتطلب أكبر قدر من الاهتمام العاجل.

مراجعة

يمكنك الآن اكتشاف التسرّبات باستخدام memcheck:

  • شغّل valgrind --leak-check=full ./prog على ملف تنفيذي مصرّف باستخدام -g
  • اقرأ LEAK SUMMARY وHEAP SUMMARY
  • أعطِ الأولوية للفئة definitely lost، ثم تتبّع التسرّبات غير المباشرة وصولًا إلى أصلها
  • استخدم --show-leak-kinds=all لتدقيق الكتل القابلة للوصول

التالي: الوصول غير الصالح إلى الذاكرة.

الأسئلة الشائعة

هل درس «اكتشاف التسربات» مجاني؟

نعم — نص درس «اكتشاف التسربات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C Academy 4 دروس في المجموع.

ماذا ستتعلم في «اكتشاف التسربات»؟

أساسيات memcheck تتمرن على C Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C Academy؟

لا تُشترط خبرة سابقة. C Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «اكتشاف التسربات»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C Academy هذا؟

نعم. كل درس في C Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. لماذا Valgrind
  2. اكتشاف التسربات
  3. الوصول غير الصالح
  4. قراءة التقارير
← العودة إلى C Academy