نمط الهادم (Destructor Pattern)
جزء من قسم Object Oriented Programming في رحلة C على Coddy — الدرس 13 من 61.
كل كائن يتم إنشاؤه باستخدام malloc يجب تحريره في النهاية. تماماً كما كتبنا دالة create_ للتعامل مع التخصيص، نكتب دالة free_ للتعامل مع عملية التنظيف. هذا هو نمط المدمر (destructor pattern).
الفكرة الأساسية هي أن عملية التحرير (freeing) يجب أن تتم بترتيب عكسي لعملية التخصيص (allocation). إذا قام المنشئ (constructor) بتخصيص الأعضاء الداخليين أولاً ثم الـ struct نفسه، فيجب على المدمر (destructor) تحرير أعضاء الـ struct أولاً، ثم الـ struct نفسه:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // التحقق من السلامة
free(p->name); // تحرير العضو الداخلي أولاً
free(p); // ثم تحرير الهيكل نفسه
}
يمنع التحقق من NULL في البداية الانهيارات في حال قام شخص ما بتمرير مؤشر غير صالح بالخطأ. بعد تحرير سلسلة name الداخلية، نقوم بتحرير الـ struct نفسه. إذا قمنا بتحرير p أولاً، فسنفقد إمكانية الوصول إلى p->name مما يتسبب في تسرب للذاكرة.
استخدام الـ destructor بسيط ومباشر:
Person *alice = create_person("Alice", 30);
// ... استخدم alice ...
free_person(alice); // قم بالتنظيف عند الانتهاء
يضمن هذا النمط تحرير جميع الذاكرة بشكل صحيح. وبدونه، سيؤدي كل كائن تنشئه إلى تسريب الذاكرة حتى ينفد برنامجك.
التحدي
سهللنقم ببناء وحدة Movie توضح دورة حياة الكائن الكاملة — الإنشاء والتدمير. ستتدرب على كتابة دالة مدمرة (destructor) تقوم بتنظيف جميع الذاكرة المخصصة بشكل صحيح وبالترتيب الصحيح.
ستقوم بإنشاء ثلاثة ملفات:
movie.h: قم بالتصريح عن هيكلMovieيحتوي على عضوين:char *title(سلسلة نصية مخصصة ديناميكيًا) وint year. قم بالتصريح عن كل من المنشئcreate_movieالذي يأخذ عنوانًا وسنة، والمدمرfree_movieالذي يأخذ مؤشر Movie. استخدم حراس التضمين (include guards) مع الرمزMOVIE_H.movie.c: قم بتنفيذ كلتا الدالتين. يجب أن يقوم المنشئ بتخصيص ذاكرة للهيكل وسلسلة العنوان الخاصة به (لا تنسَ النهاية الصفرية null terminator). يجب أن يقوم المدمر بتحرير الذاكرة بترتيب عكسي للتخصيص — أولاً سلسلةtitleالداخلية، ثم الهيكل نفسه. قم بتضمين فحص NULL في بداية المدمر الخاص بك من أجل السلامة.main.c: قم بإنشاء فيلم، واعرض معلوماته، ثم قم بتنظيف الذاكرة بشكل صحيح.
ستتلقى مدخلين: عنوان الفيلم (سلسلة نصية) و سنة الإصدار (عدد صحيح).
في ملفك الرئيسي، استخدم create_movie لإنشاء فيلم جديد، واطبع معلوماته، ثم استدعِ free_movie لتحرير كل الذاكرة. بعد التحرير، اطبع رسالة تأكيد.
اطبع المخرجات بهذا التنسيق:
Movie: {title} ({year})
Memory freedعلى سبيل المثال، مع المدخلات Inception و 2010، ستكون المخرجات:
Movie: Inception (2010)
Memory freedتذكر: المفتاح للمدمر الصحيح هو التحرير بترتيب عكسي. كل ما يخصصه المنشئ أولاً يتم تحريره آخراً، وكل ما يخصصه آخراً يتم تحريره أولاً.
ورقة مرجعية
يجب تحرير كل كائن يتم إنشاؤه باستخدام malloc باستخدام دالة مدمرة (destructor). تتبع الدوال المدمرة نمط تحرير الذاكرة بترتيب عكسي لعملية التخصيص.
الهيكل الأساسي للدالة المدمرة:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // Safety check
free(p->name); // Free internal members first
free(p); // Then free the struct itself
}
المبادئ الأساسية:
- قم دائمًا بتضمين فحص
NULLفي البداية لمنع الانهيارات (crashes) - قم بتحرير الأعضاء الداخليين قبل تحرير الهيكل (struct) نفسه
- إذا قمت بتحرير الهيكل أولاً، فستفقد إمكانية الوصول إلى أعضائه وتتسبب في تسرب الذاكرة (memory leaks)
مثال على الاستخدام:
Person *alice = create_person("Alice", 30);
// ... use alice ...
free_person(alice); // Clean up when done
جرّب بنفسك
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// قراءة المدخلات
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: إنشاء فيلم باستخدام create_movie
// TODO: طباعة معلومات الفيلم بالتنسيق التالي:
// الفيلم: {title} ({year})
// TODO: تحرير الفيلم باستخدام free_movie
// TODO: طباعة "Memory freed"
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات البرمجة التركيبية
ملفات الترويسةحواجز التضمينملفات المصدرالدوال الساكنةمراجعة: آلة حاسبة تركيبية4التغليف (Encapsulation)
مفهوم الـ Opaque Pointersتعريف الـ Opaque Structsالـ Getters والـ Settersالتحقق من البيانات في الـ Settersملخص: الصندوق السري2الكائنات والأساليب
الـ Structs ككائناتمؤشر 'Self'صحة استخدام Constالمؤشر مقابل القيمةالأساليب المساعدةملخص: Point Manager5مشروع: حساب بنكي بسيط
إعداد المشروعتنفيذ الحساب3دورة حياة الكائن
نمط المنشئ (Constructor Pattern)نمط الهادم (Destructor Pattern)تهيئة الـ Stackالنسخ العميق (Deep Copy)مراجعة: String Wrapper6الوراثة عبر التركيب
تضمين الـ Structقاعدة العضو الأولالوصول إلى أعضاء الأبعملية الـ Upcastingمراجعة: هرمية الأشكال9مشروع: رسّام الأشكال
نظرة عامة على المشروعتنفيذ الدائرة