Destructor Deseni
Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 13 / 61.
malloc ile oluşturulan her nesne en sonunda serbest bırakılmalıdır. Tıpkı bellek tahsisini (allocation) yönetmek için bir create_ fonksiyonu yazdığımız gibi, temizleme işlemini yönetmek için de bir free_ fonksiyonu yazarız. Bu, yıkıcı (destructor) desenidir.
Temel içgörü, serbest bırakma işleminin tahsis sırasının tersine gerçekleşmesi gerektiğidir. Eğer kurucunuz (constructor) önce dahili üyeleri ve ardından yapının (struct) kendisini tahsis ettiyse, yıkıcınız (destructor) önce yapının üyelerini, ardından yapının kendisini serbest bırakmalıdır:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // Güvenlik kontrolü
free(p->name); // Önce dahili üyeyi serbest bırak
free(p); // Sonra yapının kendisini serbest bırak
}
Başlangıçtaki NULL kontrolü, birisi yanlışlıkla geçersiz bir işaretçi gönderirse çökmeleri önler. Dahili name dizgisini serbest bıraktıktan sonra, yapının kendisini serbest bırakırız. Eğer önce p'yi serbest bıraksaydık, p->name'e erişimi kaybederdik ve bir bellek sızıntısına neden olurduk.
Destructor'ı kullanmak oldukça basittir:
Person *alice = create_person("Alice", 30);
// ... alice'i kullanın ...
free_person(alice); // İşlem bittiğinde temizleyin
Bu desen, tüm belleğin düzgün bir şekilde serbest bırakılmasını sağlar. Bu olmadan, oluşturduğunuz her nesne programınızın belleği bitene kadar bellek sızdıracaktır.
Görev
KolayHem oluşturma hem de yok etme süreçlerini içeren tam bir nesne yaşam döngüsünü gösteren bir Movie modülü oluşturalım. Ayrılan tüm belleği doğru sırayla düzgün bir şekilde temizleyen bir yıkıcı (destructor) fonksiyonu yazma pratiği yapacaksınız.
Üç dosya oluşturacaksınız:
movie.h: İki üyeye sahip birMovieyapısı (struct) bildirin:char *title(dinamik olarak ayrılmış bir dize) veint year. Hem bir başlık ve yıl alan bir yapıcı (constructor)create_movie, hem de bir Movie işaretçisi alan bir yıkıcı (destructor)free_moviebildirin.MOVIE_Hsembolü ile include guard kullanın.movie.c: Her iki fonksiyonu da uygulayın. Yapıcınız, yapı ve başlık dizesi için bellek ayırmalıdır (null sonlandırıcıyı unutmayın). Yıkıcınız, belleği ayırma sırasının tersine serbest bırakmalıdır—önce dahilititledizesini, ardından yapının kendisini. Güvenlik için yıkıcınızın başına bir NULL kontrolü ekleyin.main.c: Bir film oluşturun, bilgilerini görüntüleyin ve ardından belleği düzgün bir şekilde temizleyin.
İki girdi alacaksınız: film başlığı (bir dize) ve yayın yılı (bir tam sayı).
Ana dosyanızda, yeni bir film oluşturmak için create_movie kullanın, bilgilerini yazdırın ve ardından tüm belleği serbest bırakmak için free_movie çağırın. Serbest bıraktıktan sonra bir onay mesajı yazdırın.
Çıktıyı şu formatta yazdırın:
Movie: {title} ({year})
Memory freedÖrneğin, Inception ve 2010 girdileriyle çıktı şöyle olacaktır:
Movie: Inception (2010)
Memory freedUnutmayın: düzgün bir yıkıcının anahtarı, ters sırada serbest bırakmaktır. Yapıcınızın ilk ayırdığı şey en son serbest bırakılır ve en son ayırdığı şey ilk önce serbest bırakılır.
Kopya kağıdı
malloc ile oluşturulan her nesne, bir yıkıcı (destructor) fonksiyon kullanılarak serbest bırakılmalıdır. Yıkıcılar, belleği ayırma işleminin tersi sırayla serbest bırakma modelini izler.
Temel yıkıcı yapısı:
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
}
Temel ilkeler:
- Çökmeleri önlemek için her zaman başlangıçta bir
NULLkontrolü ekleyin - Yapının (struct) kendisini serbest bırakmadan önce dahili üyeleri serbest bırakın
- Önce yapıyı serbest bırakırsanız, üyelerine erişimi kaybedersiniz ve bellek sızıntılarına (memory leaks) neden olursunuz
Kullanım örneği:
Person *alice = create_person("Alice", 30);
// ... use alice ...
free_person(alice); // Clean up when done
Kendin dene
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// Girdiyi oku
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: create_movie kullanarak bir film oluşturun
// TODO: Film bilgilerini şu formatta yazdırın:
// Movie: {title} ({year})
// TODO: free_movie kullanarak filmi serbest bırakın
// TODO: "Memory freed" yazdırın
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1Modüler Programlama Temelleri
Başlık DosyalarıInclude Guard'larKaynak DosyalarıStatik FonksiyonlarÖzet: Modüler Hesap Makinesi4Kapsülleme
Opaque Pointer KavramıOpaque Struct TanımlamaGetter ve Setter MetotlarıSetter Metotlarında DoğrulamaÖzet: Gizli Kutu2Nesneler ve Metotlar
Nesne Olarak Struct'lar'Self' İşaretçisiConst Doğruluğuİşaretçi vs DeğerYardımcı MetotlarÖzet: Point Manager5Proje: Basit Banka Hesabı
Proje KurulumuHesabın Oluşturulması3Nesne Yaşam Döngüsü
Constructor DeseniDestructor DeseniStack İlklendirmeDerin KopyalamaÖzet: String Wrapper6Kompozisyon Yoluyla Kalıtım
Struct Gömmeİlk Üye KuralıÜst Üyelere ErişimUpcastingÖzet: Şekil Hiyerarşisi