4 - Dinamik Bellek Yönetimi
2026
Bellek yönetimi, programın çalışması sırasında ihtiyaç duyduğu alanın ayrılması ve işi bitince geri verilmesi ile ilgilidir.
free, yanlış adres kullanımı vb.) daha sık görülür.&x → x değişkeninin adresi*p → p’nin gösterdiği adresteki değer (dereference)int x = 5;
int *p = &x; // p, x'in adresini tutar
printf("%d\n", *p); // 5 (p'nin gösterdiği yerdeki değer)Dinamik bellek fonksiyonları (
malloc/calloc/realloc) bize bir adres döndürür.
Sabit boyutlu (önceden belirlenen) bellek kullanımının sınırları:
Dinamik bellek yönetimi ne sağlar?
Bu derste üç temel alanı ayırt etmek yeterlidir:
Stack (otomatik bellek):
Heap (dinamik bellek):
malloc/calloc/realloc ile ayrılan alanfree etmeden geri verilmezGlobal/Static alan:
static ile tanımlananlarYüksek adresler
+------------------------------+
| STACK | <- yerel değişkenler
| (fonksiyon çağrıları) | (genelde aşağı doğru büyür)
+------------------------------+
| (boşluk) |
| |
+------------------------------+
| HEAP | <- malloc/calloc/realloc
| (dinamik ayrılan alan) | (genelde yukarı doğru büyür)
+------------------------------+
| Global / Static alan | <- program boyunca yaşar
+------------------------------+
| Kod alanı |
+------------------------------+
Düşük adreslerNot: Bu çizim temsildir. Ayrıntılı bellek segmentlerini (text/BSS vb.) bu seviyede ayrı ayrı ele almayacağız.
| Özellik | Stack (Otomatik) | Heap (Dinamik) |
|---|---|---|
| Ayırma zamanı | Fonksiyon çalışırken | Program çalışırken istenen anda |
| Bırakma | Fonksiyon bitince otomatik | free() ile manuel |
| Boyut | Genelde daha sınırlı | Genelde daha esnek |
| Kullanım amacı | Kısa ömürlü yerel değişkenler | Değişken boyutlu veri yapıları |
C dilinde dinamik bellek yönetimi için standart kütüphanede (stdlib.h) bulunan fonksiyonlar kullanılır:
malloc() : Bellek ayırma (ilk değer yok)calloc() : Bellek ayırma + sıfırlamarealloc(): Ayrılmış belleği yeniden boyutlandırmafree() : Ayrılmış belleği serbest bırakmamalloc() - Bellek AyırmaGeri dönüş:
NULLint için bellek ayırma#include <stdio.h>
#include <stdlib.h>
int main(void) {
int boyut = 10;
// Önerilen kalıp: sizeof(*ptr)
int *dizi = malloc((size_t)boyut * sizeof *dizi);
if (dizi == NULL) {
printf("Bellek ayırma başarısız!\n");
return 1;
}
printf("Bellek başarıyla ayrıldı.\n");
for (int i = 0; i < boyut; i++) {
dizi[i] = i * 2;
}
for (int i = 0; i < boyut; i++) {
printf("%d ", dizi[i]);
}
printf("\n");
free(dizi);
dizi = NULL;
return 0;
}calloc() - Bellek Ayırma ve Sıfırlamanum * size kadar alan ayırır ve ayrılan baytları 0 yapar.calloc ile ayrılan alan, pratikte tamsayılar için 0 başlangıcına denk gelir.int için bellek ayırma ve sıfırlama#include <stdio.h>
#include <stdlib.h>
int main(void) {
int boyut = 10;
int *dizi = calloc((size_t)boyut, sizeof *dizi);
if (dizi == NULL) {
printf("Bellek ayırma başarısız!\n");
return 1;
}
printf("Bellek başarıyla ayrıldı ve sıfırlandı.\n");
for (int i = 0; i < boyut; i++) {
printf("%d ", dizi[i]); // hepsi 0 beklenir
}
printf("\n");
free(dizi);
dizi = NULL;
return 0;
}realloc() - Belleği Yeniden BoyutlandırmaNULL döner ve eski blok yerinde kalır.realloc() için Güvenli Kullanım Kuralırealloc sonucunu doğrudan eski pointer’a yazmayın.#include <stdio.h>
#include <stdlib.h>
int main(void) {
int eski_boyut = 5;
int yeni_boyut = 10;
int *dizi = malloc((size_t)eski_boyut * sizeof *dizi);
if (!dizi) {
printf("Bellek ayırma başarısız!\n");
return 1;
}
for (int i = 0; i < eski_boyut; i++) {
dizi[i] = i + 1;
}
printf("Başlangıç dizisi: ");
for (int i = 0; i < eski_boyut; i++) printf("%d ", dizi[i]);
printf("\n"); int *tmp = realloc(dizi, (size_t)yeni_boyut * sizeof *dizi);
if (!tmp) {
printf("Bellek yeniden boyutlandırma başarısız!\n");
free(dizi);
return 1;
}
dizi = tmp;
// Yeni eklenen elemanları mutlaka BAŞLAT
for (int i = eski_boyut; i < yeni_boyut; i++) {
dizi[i] = 0;
}
printf("Büyütülmüş dizi: ");
for (int i = 0; i < yeni_boyut; i++) printf("%d ", dizi[i]);
printf("\n");
free(dizi);
dizi = NULL;
return 0;
}free() - Belleği Serbest Bırakmaptr == NULL ise free(NULL) hiçbir şey yapmaz (güvenlidir).free sonrası o adresi kullanmak tanımsız davranış üretir.Bellek Sızıntısı (Memory Leak):
Sarkan İşaretçi (Dangling Pointer):
Çift Serbest Bırakma (Double Free):
malloc/calloc/realloc dönüşünü mutlaka kontrol edin (NULL olabilir).sizeof(*ptr) kalıbını tercih edin.realloc için geçici pointer kullanın (tmp).free sonrası pointer’ı NULL yapın.free(ptr) kullanın; realloc(ptr, 0) gibi kalıpları bu derste kullanmayacağız.Dinamik Diziler (Resizable Arrays):
malloc ile başlat, ihtiyaç olunca realloc ile büyüt/küçültDinamik Metinler (String):
realloc ile artırmaBağlı Liste gibi yapılar (ileride):
malloc ile oluşturulurDinamik bellek, program çalışırken bellek ayırma ve geri verme imkânı sağlar.
C’de bu işlem malloc, calloc, realloc, free ile yapılır.
En sık hatalar: memory leak, dangling pointer, double free.
Güvenli kullanım için:
NULL kontrolüsizeof(*ptr) kalıbırealloc için geçici pointerfree sonrası NULL