0Pricing
C Academy · درس

تحرير الذاكرة وتجنّب التسريبات

نظّف الموارد بطريقة صحيحة

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

كل malloc تحتاج إلى free

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

تتراكم التسريبات بمرور الوقت، وقد تستنزف الذاكرة في البرامج طويلة التشغيل.

int *a = malloc(100 * sizeof(*a));
/* ... use a ... */
free(a);

ما الذي تفعله free فعليًا

تعيد free(p) الكتلة إلى مخصّص الذاكرة حتى يمكن إعادة استخدامها. لكنها لا تغيّر قيمة p نفسها.

بعد استدعاء free، يظل p مشيرًا إلى العنوان القديم، الذي أصبح غير صالح الآن. واستخدامه يؤدي إلى سلوك غير معرّف.

free(p);
/* p is now a dangling pointer */

فخ المؤشر المتدلّي

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

ومن وسائل الحماية البسيطة ضبط المؤشر على NULL مباشرة بعد تحريره.

free(a);
a = NULL;   /* now misuse is a clean NULL deref, easier to catch */

التحرير المزدوج سلوك غير معرّف

يؤدي استدعاء free مرتين للكتلة نفسها إلى إفساد الحالة الداخلية لمخصّص الذاكرة، وغالبًا إلى تعطل البرنامج.

يساعد ضبط المؤشر على NULL بعد أول عملية تحرير، لأن free(NULL) آمنة صراحة ولا تفعل شيئًا.

free(a);
a = NULL;
free(a);   /* free(NULL) is a harmless no-op */

حرّر ما خصّصته باستخدام malloc فقط

مرّر إلى free مؤشرًا مصدره malloc أو calloc أو realloc فقط.

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

int x = 5;
/* free(&x);   WRONG: x is on the stack */
int *p = malloc(sizeof(int));
free(p);        /* correct */

تسرّب بسبب العودة المبكرة

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

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

int *a = malloc(n * sizeof(*a));
if (something_failed) {
    free(a);   /* don't forget this before returning */
    return -1;
}

برنامج نظيف للتخصيص والتحرير

يخصّص هذا البرنامج الذاكرة ويستخدمها ويحررها في كل مسار، من دون أي تسريبات.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int n = 4;
    int *a = malloc(n * sizeof(*a));
    if (!a) return 1;
    for (int i = 0; i < n; i++) a[i] = i + 1;
    int sum = 0;
    for (int i = 0; i < n; i++) sum += a[i];
    printf("%d\n", sum);
    free(a);
    a = NULL;
    return 0;
}

تحرير التخصيصات المتداخلة

إذا احتوت كتلة على مؤشرات إلى كتل أخرى، فحرّر الكتل الداخلية أولًا، ثم الكتلة الخارجية.

فلو حرّرت الكتلة الخارجية أولًا، لفقدت عناوين الكتل الداخلية وتسربت تلك الكتل.

for (size_t i = 0; i < rows; i++)
    free(grid[i]);   /* free each row first */
free(grid);          /* then the array of pointers */

مالك واحد لكل كتلة

حدّد الجزء من شيفرتك الذي يملك كل تخصيص ويتحمّل مسؤولية تحريره.

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

اكتشاف التسريبات باستخدام الأدوات

لست مضطرًا إلى اكتشاف التسريبات بالنظر إلى الشيفرة. فأدوات مثل valgrind أو AddressSanitizer تُبلغ عن التسريبات وعمليات التحرير غير الصالحة مع أرقام الأسطر.

جمّع البرنامج باستخدام -g وشغّله تحت الأداة لترى بالضبط ما لم يُحرر.

/* gcc -g -fsanitize=address prog.c && ./a.out */
/* or: valgrind --leak-check=full ./a.out */

التحرير بترتيب عكسي للإعداد

من العادات الموثوقة أنه عند الحصول على عدة موارد داخل دالة، تُحررها بالترتيب العكسي لترتيب الحصول عليها.

وهذا يحاكي طريقة بناء التبعيات، ويحافظ على قابلية التنبؤ بعملية التنظيف.

char *buf = malloc(64);
int  *idx = malloc(64 * sizeof(int));
/* ... use them ... */
free(idx);   /* free last-acquired first */
free(buf);

تحقّق سريع

اختبر مدى فهمك لتحرير الذاكرة.

مراجعة

قابل كل عملية تخصيص بعملية free واحدة بالضبط، في كل مسار من مسارات الشيفرة.

تجنّب المؤشرات المتدلّية والتحرير المزدوج بضبط المؤشرات على NULL بعد تحريرها. حرّر التخصيصات المتداخلة بدءًا من الداخلية، وامنح كل كتلة مالكًا واحدًا، واستخدم valgrind أو ASan لاكتشاف التسريبات. لديك الآن مجموعة الأدوات الكاملة للمصفوفات الديناميكية.

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

هل درس «تحرير الذاكرة وتجنّب التسريبات» مجاني؟

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

ماذا ستتعلم في «تحرير الذاكرة وتجنّب التسريبات»؟

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

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

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

كم من الوقت يستغرق درس «تحرير الذاكرة وتجنّب التسريبات»؟

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

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

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

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

  1. تخصيص مصفوفة
  2. التوسعة باستخدام realloc
  3. نوع Vector قابل لإعادة الاستخدام
  4. تحرير الذاكرة وتجنّب التسريبات
← العودة إلى C Academy