-
Sadrazamv4
ig:sadrazam_v4 tg: Sadrazam.spy
🚀 BAŞTAN SONA C DİLİ BÖLÜM-8: Dinamik Bellek Yönetimi (`malloc`, `calloc`, `realloc`, `free`) 🧠
Selamlar! Serimizin 8. bölümüne hoş geldiniz.
Önceki bölümde dizileri, metin (String) mantığını ve `<string.h>` kütüphanesini incelemiştik. Şu ana kadar tanımladığımız tüm dizilerin boyutları **derleme zamanında (compile-time)** sabitti (Örn: `int dizi[100];`). Peki ya kullanıcının kaç eleman gireceğini program çalışmadan önce bilmiyorsak? Boşuna 1000 elemanlık yer açıp belleği israf mı edeceğiz?
İşte bu noktada devreye C dilinin en büyük gücü olan **Dinamik Bellek Yönetimi (Dynamic Memory Allocation - DMA)** giriyor! Bu işlemler için programımıza mutlaka **`<stdlib.h>`** kütüphanesini dahil etmemiz gerekir.
---
📌 1. Bellek Mimarisi: Stack vs Heap 🏛️
C programları çalışırken RAM'i iki ana bölüme ayırır:
1. **Stack (Yığın):** Normal değişkenlerin (`int a = 5;` veya `char isim[20];`) tutulduğu yerdir. Boyutları derleme anında bellidir. Fonksiyon bitince bellek otomatik temizlenir. Oldukça hızlı ama kapasitesi kısıtlıdır.
2. **Heap (Öbek):** Dinamik belleğin ayrıldığı, devasa boş bellek havuzudur. Buradan yer ayırmak ve işi bitince geri iade etmek **tamamen programcının (sizin) sorumluluğunuzdadır.**
---
🛠️ 2. `malloc()` (Memory Allocation) 📦
Heap bölgesinden **belirtilen byte kadar** tek parça bellek alanı ayırır. Ayırdığı alanın başlangıç adresini `void*` (türsüz pointer) olarak döner. Bu alanın içi temizlenmez, rastgele **çöp değerler (garbage values)** içerir.
Sözdizimi: `(Tur*) malloc(Eleman_Sayisi * sizeof(Tur));`
#include <stdio.h>
#include <stdlib.h> // malloc, free için zorunlu!
int main() {
int n;
printf("Kac adet sayi gireceksiniz?: ");
scanf("%d", &n);
// Heap'ten n adet int boyutunda (n * 4 byte) yer ayırıyoruz
int *ptr = (int*) malloc(n * sizeof(int));
// KURAL 1: Bellek ayrılabildi mi kontrol et! (RAM dolmuş olabilir)
if (ptr == NULL) {
printf("HATA: Bellekte yeterli yer yok!\n");
return 1; // Programı hata koduyla bitir
}
printf("Bellek tahsisi basarili!\n");
return 0;
}
---
🧼 3. `calloc()` (Contiguous Allocation) 🧽
`malloc` ile aynı işi yapar ancak iki önemli farkı vardır:
1. Parametreleri farklıdır: `(Eleman Sayısı, Her Birinin Boyutu)`.
2. Ayırdığı bellek alanındaki tüm bitleri otomatik olarak **0 ile doldurur (temizler).**
Sözdizimi: `(Tur*) calloc(Eleman_Sayisi, sizeof(Tur));`
// 5 adet int için yer ayırır ve hepsine 0 değerini atar
int *ptr = (int*) calloc(5, sizeof(int));
---
📏 4. `realloc()` (Re-allocation) 📐
Daha önceden `malloc` veya `calloc` ile ayırdığınız bir bellek alanının **boyutunu çalışma zamanında büyütmek veya küçültmek** isterseniz kullanılır. Orijinal verileri koruyarak yeni boyuta adapte eder.
Sözdizimi: `(Tur*) realloc(Eski_Pointer, Yeni_Toplam_Byte);`
// Dizinin boyutunu n'den (n+5)'e çıkaralım
ptr = (int*) realloc(ptr, (n + 5) * sizeof(int));
---
🚨 5. `free()` ve Memory Leak (Bellek Sızıntısı) 💣
C dilinde, Java veya C#'taki gibi otomatik Çöp Toplayıcı (Garbage Collector) **YOKTUR**. Heap'ten ayırdığınız belleği işiniz bittiğinde sisteme **iade etmek ZORUNDASINIZ.**
Eğer iade etmezseniz ve program uzun süre çalışırsa (örneğin bir oyun veya sunucu), RAM yavaş yavaş dolar ve sonunda sistem kilitlenir. Buna **Memory Leak (Bellek Sızıntısı)** denir.
// İşi biten bellek alanını sisteme iade eder
free(ptr);
// Güvenlik Pratiği (Dangling Pointer'ı önlemek için):
ptr = NULL;
---
🧪 6. Kapsamlı Dinamik Dizi Örneği 🚀
Gelin boyutu kullanıcı tarafından belirlenen, elemanları atanan ve işi bitince hafızası temizlenen tam teşekküllü bir program yazalım.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, i;
int *notlar;
printf("Sinif mevcudunu giriniz: ");
scanf("%d", &n);
// 1. Adım: Bellek Tahsisi
notlar = (int*) malloc(n * sizeof(int));
// 2. Adım: NULL Kontrolü
if (notlar == NULL) {
printf("Hata: Bellek tahsis edilemedi!\n");
return -1;
}
// 3. Adım: Veri Girişi (Array gibi kullanılabilir)
for (i = 0; i < n; i++) {
printf("%d. Ogrencinin Notu: ", i + 1);
scanf("%d", ¬lar); // veya (notlar + i)
}
// 4. Adım: Verileri Ekrana Yazdırma
printf("\n--- NOT LISTESI ---\n");
for (i = 0; i < n; i++) {
printf("Ogrenci %d: %d\n", i + 1, notlar);
}
// 5. Adım: Tahsis Edilen Belleği Temizleme (Hayat Kurtarır!)
free(notlar);
notlar = NULL; // Güvenlik amacıyla sıfırlama
return 0;
}
---
📝 Bölüm Özeti ve Gelecek Bölüm 🔮
Bu bölümde Stack/Heap mantığını, C dilinin kalbi olan DMA (Dinamik Bellek Yönetimi) fonksiyonlarını (`malloc`, `calloc`, `realloc`) ve uygulamalarımızı çökmekten kurtaran `free()` komutunu öğrendik.
👉 **Bölüm 9'da Bizi Ne Bekliyor?**
• Kendi Veri Tiplerimizi Oluşturma: **Yapılar (`struct`)** 🏗️
• `struct` Tanımlama ve Nesne (Değişken) Üretme
• **`typedef`** Anahtar Kelimesi ile İsimlendirme
• Struct Dizileri (Veritabanı mantığına hazırlık)
• Bellek Optimizasyonu: **`union`** (Birlik) Kavramı
Sorularınızı konu altından iletebilirsiniz. Bir sonraki bölümde görüşmek üzere! 💻✨
Selamlar! Serimizin 8. bölümüne hoş geldiniz.
Önceki bölümde dizileri, metin (String) mantığını ve `<string.h>` kütüphanesini incelemiştik. Şu ana kadar tanımladığımız tüm dizilerin boyutları **derleme zamanında (compile-time)** sabitti (Örn: `int dizi[100];`). Peki ya kullanıcının kaç eleman gireceğini program çalışmadan önce bilmiyorsak? Boşuna 1000 elemanlık yer açıp belleği israf mı edeceğiz?
İşte bu noktada devreye C dilinin en büyük gücü olan **Dinamik Bellek Yönetimi (Dynamic Memory Allocation - DMA)** giriyor! Bu işlemler için programımıza mutlaka **`<stdlib.h>`** kütüphanesini dahil etmemiz gerekir.
---
📌 1. Bellek Mimarisi: Stack vs Heap 🏛️
C programları çalışırken RAM'i iki ana bölüme ayırır:
1. **Stack (Yığın):** Normal değişkenlerin (`int a = 5;` veya `char isim[20];`) tutulduğu yerdir. Boyutları derleme anında bellidir. Fonksiyon bitince bellek otomatik temizlenir. Oldukça hızlı ama kapasitesi kısıtlıdır.
2. **Heap (Öbek):** Dinamik belleğin ayrıldığı, devasa boş bellek havuzudur. Buradan yer ayırmak ve işi bitince geri iade etmek **tamamen programcının (sizin) sorumluluğunuzdadır.**
---
🛠️ 2. `malloc()` (Memory Allocation) 📦
Heap bölgesinden **belirtilen byte kadar** tek parça bellek alanı ayırır. Ayırdığı alanın başlangıç adresini `void*` (türsüz pointer) olarak döner. Bu alanın içi temizlenmez, rastgele **çöp değerler (garbage values)** içerir.
Sözdizimi: `(Tur*) malloc(Eleman_Sayisi * sizeof(Tur));`
#include <stdio.h>
#include <stdlib.h> // malloc, free için zorunlu!
int main() {
int n;
printf("Kac adet sayi gireceksiniz?: ");
scanf("%d", &n);
// Heap'ten n adet int boyutunda (n * 4 byte) yer ayırıyoruz
int *ptr = (int*) malloc(n * sizeof(int));
// KURAL 1: Bellek ayrılabildi mi kontrol et! (RAM dolmuş olabilir)
if (ptr == NULL) {
printf("HATA: Bellekte yeterli yer yok!\n");
return 1; // Programı hata koduyla bitir
}
printf("Bellek tahsisi basarili!\n");
return 0;
}
---
🧼 3. `calloc()` (Contiguous Allocation) 🧽
`malloc` ile aynı işi yapar ancak iki önemli farkı vardır:
1. Parametreleri farklıdır: `(Eleman Sayısı, Her Birinin Boyutu)`.
2. Ayırdığı bellek alanındaki tüm bitleri otomatik olarak **0 ile doldurur (temizler).**
Sözdizimi: `(Tur*) calloc(Eleman_Sayisi, sizeof(Tur));`
// 5 adet int için yer ayırır ve hepsine 0 değerini atar
int *ptr = (int*) calloc(5, sizeof(int));
---
📏 4. `realloc()` (Re-allocation) 📐
Daha önceden `malloc` veya `calloc` ile ayırdığınız bir bellek alanının **boyutunu çalışma zamanında büyütmek veya küçültmek** isterseniz kullanılır. Orijinal verileri koruyarak yeni boyuta adapte eder.
Sözdizimi: `(Tur*) realloc(Eski_Pointer, Yeni_Toplam_Byte);`
// Dizinin boyutunu n'den (n+5)'e çıkaralım
ptr = (int*) realloc(ptr, (n + 5) * sizeof(int));
---
🚨 5. `free()` ve Memory Leak (Bellek Sızıntısı) 💣
C dilinde, Java veya C#'taki gibi otomatik Çöp Toplayıcı (Garbage Collector) **YOKTUR**. Heap'ten ayırdığınız belleği işiniz bittiğinde sisteme **iade etmek ZORUNDASINIZ.**
Eğer iade etmezseniz ve program uzun süre çalışırsa (örneğin bir oyun veya sunucu), RAM yavaş yavaş dolar ve sonunda sistem kilitlenir. Buna **Memory Leak (Bellek Sızıntısı)** denir.
// İşi biten bellek alanını sisteme iade eder
free(ptr);
// Güvenlik Pratiği (Dangling Pointer'ı önlemek için):
ptr = NULL;
---
🧪 6. Kapsamlı Dinamik Dizi Örneği 🚀
Gelin boyutu kullanıcı tarafından belirlenen, elemanları atanan ve işi bitince hafızası temizlenen tam teşekküllü bir program yazalım.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, i;
int *notlar;
printf("Sinif mevcudunu giriniz: ");
scanf("%d", &n);
// 1. Adım: Bellek Tahsisi
notlar = (int*) malloc(n * sizeof(int));
// 2. Adım: NULL Kontrolü
if (notlar == NULL) {
printf("Hata: Bellek tahsis edilemedi!\n");
return -1;
}
// 3. Adım: Veri Girişi (Array gibi kullanılabilir)
for (i = 0; i < n; i++) {
printf("%d. Ogrencinin Notu: ", i + 1);
scanf("%d", ¬lar); // veya (notlar + i)
}
// 4. Adım: Verileri Ekrana Yazdırma
printf("\n--- NOT LISTESI ---\n");
for (i = 0; i < n; i++) {
printf("Ogrenci %d: %d\n", i + 1, notlar);
}
// 5. Adım: Tahsis Edilen Belleği Temizleme (Hayat Kurtarır!)
free(notlar);
notlar = NULL; // Güvenlik amacıyla sıfırlama
return 0;
}
---
📝 Bölüm Özeti ve Gelecek Bölüm 🔮
Bu bölümde Stack/Heap mantığını, C dilinin kalbi olan DMA (Dinamik Bellek Yönetimi) fonksiyonlarını (`malloc`, `calloc`, `realloc`) ve uygulamalarımızı çökmekten kurtaran `free()` komutunu öğrendik.
👉 **Bölüm 9'da Bizi Ne Bekliyor?**
• Kendi Veri Tiplerimizi Oluşturma: **Yapılar (`struct`)** 🏗️
• `struct` Tanımlama ve Nesne (Değişken) Üretme
• **`typedef`** Anahtar Kelimesi ile İsimlendirme
• Struct Dizileri (Veritabanı mantığına hazırlık)
• Bellek Optimizasyonu: **`union`** (Birlik) Kavramı
Sorularınızı konu altından iletebilirsiniz. Bir sonraki bölümde görüşmek üzere! 💻✨
🔒 Bu içeriği görmek için giriş yapın