תבנית הורס
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C של Coddy. שיעור 13 מתוך 61.
יש לשחרר בסופו של דבר כל אובייקט שנוצר באמצעות malloc. בדיוק כפי שכתבנו פונקציית create_ לטיפול בהקצאה, אנחנו כותבים פונקציית free_ לטיפול בניקוי. זוהי תבנית ההורס.
התובנה המרכזית היא שהשחרור חייב להתבצע בסדר הפוך לסדר ההקצאה. אם הבנאי שלך הקצה תחילה את האיברים הפנימיים ואז את המבנה עצמו, המשמיד שלך חייב לשחרר תחילה את איברי המבנה, ואז את המבנה:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // בדיקת בטיחות
free(p->name); // תחילה יש לשחרר את השדה הפנימי
free(p); // לאחר מכן יש לשחרר את ה-struct עצמו
}
הבדיקה של NULL בתחילת הפונקציה מונעת קריסות אם מישהו מעביר בטעות מצביע לא תקין. אחרי שמשחררים את מחרוזת ה־name הפנימית, משחררים את המבנה עצמו. אם היינו משחררים קודם את p, היינו מאבדים את הגישה ל־p->name וגורמים לדליפת זיכרון.
השימוש בהורס פשוט:
Person *alice = create_person("Alice", 30);
// ... השתמשו ב-alice ...
free_person(alice); // שחררו משאבים בסיום
התבנית הזאת מבטיחה שכל הזיכרון ישוחרר כראוי. בלעדיה, כל אובייקט שתיצור יגרום לדליפת זיכרון עד שהתוכנית שלך תיגמר בו.
אתגר
קלנבנה מודול Movie שמדגים את מחזור החיים המלא של אובייקט: גם יצירה וגם השמדה. תתרגלו לכתוב פונקציית הרס שמשחררת כראוי את כל הזיכרון שהוקצה, בסדר הנכון.
תיצרו שלושה קבצים:
movie.h: הצהירו על מבנהMovieעם שני איברים:char *title(מחרוזת שהוקצה לה זיכרון באופן דינמי) ו-int year. הצהירו על בנאיcreate_movieשמקבל כותרת ושנה, ועל פונקציית הרסfree_movieשמקבלת מצביע ל-Movie. השתמשו במשמרות הכללה עם הסמלMOVIE_H.movie.c: ממשו את שתי הפונקציות. הבנאי שלכם צריך להקצות זיכרון למבנה ולמחרוזת הכותרת שלו (אל תשכחו את תו הסיום null). פונקציית ההרס חייבת לשחרר את הזיכרון בסדר הפוך לסדר ההקצאה: תחילה את מחרוזת ה-titleהפנימית, ולאחר מכן את המבנה עצמו. הוסיפו בדיקת NULL בתחילת פונקציית ההרס, ליתר ביטחון.main.c: צרו סרט, הציגו את המידע שלו, ואז שחררו כראוי את הזיכרון.
תקבלו שני קלטים: כותרת הסרט (מחרוזת) ושנת ההפצה (מספר שלם).
בקובץ הראשי שלכם, השתמשו ב-create_movie כדי ליצור סרט חדש, הדפיסו את המידע שלו, ואז קראו ל-free_movie כדי לשחרר את כל הזיכרון. לאחר השחרור, הדפיסו הודעת אישור.
הדפיסו את הפלט בפורמט הזה:
Movie: {title} ({year})
Memory freedלדוגמה, עבור הקלטים Inception ו-2010, הפלט יהיה:
Movie: Inception (2010)
Memory freedזכרו: המפתח לפונקציית הרס תקינה הוא שחרור בסדר הפוך. מה שהבנאי שלכם מקצה ראשון משתחרר אחרון, ומה שהוא מקצה אחרון משתחרר ראשון.
נסו בעצמכם
#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;
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
4כימוס
המושג של מצביעים אטומיםהגדרת מבנים אטומיםפונקציות Get ו-Setאימות ב-Settersסיכום: הקופסה הסודית2אובייקטים ומתודות
מבנים כאובייקטיםמצביע 'Self'נכונות constמצביע לעומת ערךמתודות עזרחזרה: מנהל נקודות5פרויקט: חשבון בנק פשוט
הגדרת הפרויקטמימוש החשבוןתרגלו בעצמכם: קומפיילר C אונליין