---
title: 'Bellek Düzeni'
source: 'https://academia.sh/tr/kurslar/c-bellek/bellek-duzeni'
course: "C'de Bellek ve İşaretçiler"
language: tr
updated: '2026-09-26T03:02:43+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Otomatik, statik ve dinamik bölgelerin sahiplik sınıflarıyla nasıl örtüştüğünü gösterir'
    - 'Dört dil gözlemini ayir ve birak gözlemiyle karşılaştırarak sayaç farkının yalnız dinamik bölgede kıpırdadığını ölçer'
    - 'Bölge sınırlarını ve hizalama değerlerini basmadan, bölgenin sahiplikle ilişkisini açıklar'
---

# Bellek Düzeni

Bir programın belleği tek bir alan değildir; otomatik, statik ve dinamik olmak üzere ayrı bölgelere bölünür ve bir bloğun hangi bölgede durduğu, onun sahibinin kim olacağını baştan belirler. Ders dört dil gözlemini ayir ve birak gözlemiyle yan yana koyup bu ayrımı adres basmadan ölçüyor.

Dinamik Bellek konusunun önceki dört dersi belleğin **dinamik** bölgesinde kaldı: `malloc`, `calloc`,
`realloc`, sahiplik sözleşmesi, sızıntı, denetim noktası — hepsi çalışma zamanında ayrılan
ve elle bırakılan bloklarla ilgiliydi. Ama bu kursun ilk dersinden beri her ölçümde `dil`
sınıfı da vardı: yerel değişkenler, statik alanlar, dizgi değişmezleri. Bu ders, konuyu
kapatırken, dinamik bölgeyi geri kalan üç bölgenin **yanına** koyuyor ve bir bloğun hangi
bölgede durduğunun, sahibinin kim olacağını nasıl baştan belirlediğini gösteriyor.

## Dört Bölge, Bir Soru

Bir C programının belleği birden çok bölgeye ayrılır: kodun kendisi, sabit veri, statik
değişkenler, çalışma zamanı yığıtı (otomatik değişkenler için) ve öbek (dinamik ayırma
için). Bu bölgelerin donanımda nasıl yerleştiği ve aralarındaki sınırların nasıl hizalandığı
Bilgisayarlar Nasıl Çalışır kursunda (M01/K01) ele alındı; bu ders o düzeni
yeniden anlatmıyor, yalnız **sahiplik** sorusuyla ilişkilendiriyor. Soru hep aynı: bu
bloğu kim bırakacak? Yanıt, bloğun hangi bölgede durduğuna bağlı.

```c
// sayac.h — her ayirmayi ve her birakmayi sayan sarmalayici
#ifndef SAYAC_H
#define SAYAC_H

#include <stddef.h>

void *say_ayir(size_t boyut);
void *say_buyut(void *eski, size_t boyut);
void say_birak(void *blok);
int ayrilan_sayisi(void);
int birakilan_sayisi(void);

#endif
```

```c
// sayac.c — sayaclar yalniz bu birimde tutulur
#include <stdlib.h>
#include "sayac.h"

static int ayrilan = 0;
static int birakilan = 0;

void *say_ayir(size_t boyut) {
    void *blok = malloc(boyut);
    if (blok != NULL) {
        ayrilan++;
    }
    return blok;
}

void *say_buyut(void *eski, size_t boyut) {
    int yeni_blok = (eski == NULL);
    void *yeni = realloc(eski, boyut);
    if (yeni != NULL && yeni_blok) {
        ayrilan++;
    }
    return yeni;
}

void say_birak(void *blok) {
    if (blok != NULL) {
        birakilan++;
    }
    free(blok);
}

int ayrilan_sayisi(void) {
    return ayrilan;
}

int birakilan_sayisi(void) {
    return birakilan;
}
```

```c
// duzen.c — dort dil gozlemi ile ayir ve birak karsitligi
#include <stdio.h>
#include <string.h>
#include "sayac.h"

static int sabit_statik = 3;

static int fark(void) {
    return ayrilan_sayisi() - birakilan_sayisi();
}

static void gozle(const char *ad, const char *sinif, const char *kanit) {
    printf("%-30s%-10s%s\n", ad, sinif, kanit);
}

int main(void) {
    char tampon[64];
    int once;

    printf("%-30s%-10s%s\n", "gozlem", "sahip", "kanit");

    /* --- dil: otomatik bolge, kapsam bitince kendiliginden geri alinir --- */
    once = fark();
    int yerel = 5;
    int *p = &yerel;
    snprintf(tampon, sizeof tampon, "*p %d, sayac farki %d", *p, fark() - once);
    gozle("yerel degisken", "dil", tampon);

    /* --- dil: statik bolge, program boyunca tek bir yerde durur --- */
    int *s = &sabit_statik;
    snprintf(tampon, sizeof tampon, "*s %d, birakma cagrisi yok", *s);
    gozle("statik alan", "dil", tampon);

    /* --- dil: sabit veri bolgesi, degismez metin --- */
    const char *degismez = "sabit";
    snprintf(tampon, sizeof tampon, "uzunluk %d, birakma cagrisi yok", (int)strlen(degismez));
    gozle("dizgi degismezi", "dil", tampon);

    /* --- dil: otomatik bolgede yasayan bir dizi --- */
    int dizi[4] = {1, 2, 3, 4};
    int *ilk = dizi;
    int *son = &dizi[3];
    snprintf(tampon, sizeof tampon, "son - ilk %d, *son %d", (int)(son - ilk), *son);
    gozle("yerel dizi", "dil", tampon);

    /* --- cagiran: obek bolgesi, elle ayrilir ve elle birakilir --- */
    once = fark();
    int *blok = say_ayir(4 * sizeof *blok);
    int toplam = 0;
    if (blok != NULL) {
        for (int i = 0; i < 4; i++) {
            blok[i] = i + 1;
            toplam += blok[i];
        }
    }
    say_birak(blok);
    snprintf(tampon, sizeof tampon, "toplam %d, sayac farki %d", toplam, fark() - once);
    gozle("ayir ve birak", "cagiran", tampon);

    return 0;
}
```

```
gozlem                        sahip     kanit
yerel degisken                dil       *p 5, sayac farki 0
statik alan                   dil       *s 3, birakma cagrisi yok
dizgi degismezi               dil       uzunluk 5, birakma cagrisi yok
yerel dizi                    dil       son - ilk 3, *son 4
ayir ve birak                 cagiran   toplam 10, sayac farki 0
```

**BE16.** Dört `dil` gözleminin dördünde de sayaç hiç kıpırdamadı — `yerel degisken` ve
`yerel dizi` otomatik bölgede, `statik alan` statik bölgede, `dizgi degismezi` sabit veri
bölgesinde durur; üçü de programın **kendisi tarafından**, kapsam ya da program ömrüyle
geri alınır. `ayir ve birak` gözlemi ise öbek bölgesindedir ve sayaç farkı yine **0**
verir — ama bu kez sıfır, dilin kendiliğinden yaptığı bir şeyden değil, `say_ayir`'in
karşılığında yazılan `say_birak`'tan geliyor. Aynı sonuç (**fark 0**), iki farklı nedenden
geliyor: biri hiç ölçülmediği için sıfır, öteki ölçülüp dengelendiği için sıfır.

## Bölge Sahibi Belirler, Sahip Bölgeyi Belirlemez

Bir bloğun hangi bölgede durduğu, çoğu zaman **bildirimin kendisinden** bellidir: bir işlev
içinde `int yerel = 5;` yazmak otomatik bölgeye, dosya kapsamında ya da `static` anahtar
sözcüğüyle bildirmek statik bölgeye, bir dizgi değişmezi yazmak sabit veri bölgesine, ve
`say_ayir` (ya da doğrudan `malloc`) çağırmak öbek bölgesine yerleştirir. Sahiplik sınıfı
bu bildirimden **türer**: otomatik ve statik bölgedeki hiçbir blok bırakma çağrısı
almaz, sahibi hep **dil**dir; öbek bölgesindeki her blok bir bırakma çağrısı bekler, sahibi
**çağırandır** (ya da `Serbest Bırakma Disiplini` dersinde görüldüğü gibi, sözleşmeye göre
**çağrılandır**). Bölge tek başına yeterli değildir — öbek bölgesindeki bir bloğun
çağırana mı çağrılana mı ait olduğunu bölgenin kendisi söylemez, bunu yine `sahip.h` gibi
bir sözleşme belirler. Ama otomatik ve statik bölge için bölge tek başına **yeterlidir**:
oraya yerleşen hiçbir blok hiçbir zaman elle bırakılmaz.

## İç İçe Kapsam da Dil Sınıfındadır

Yukarıdaki dört `dil` gözlemi hepsi `main`'in en dış kapsamındaydı. Ama otomatik bölgenin
kuralı kapsamın **derinliğine** bakmaz — bir işlevin gövdesi içindeki her `{ }` bloğu kendi
otomatik ömrünü taşır ve iç içe geçmiş bir blok da dış blok kadar dil sınıfındadır. Aynı
zamanda, dinamik tarafta bir bloğun **boyutu** büyüdükçe bunun sahiplik sınıfını
değiştirmediğini de göstermek mümkün: ister dört elemanlık ister kırk elemanlık olsun,
`say_ayir`'den dönen her blok yine çağırana aittir.

```c
// icice.c — ic ice otomatik kapsam ile boyutu buyuyen obek bloginin karsitligi
#include <stdio.h>
#include "sayac.h"

static int fark(void) {
    return ayrilan_sayisi() - birakilan_sayisi();
}

static void gozle(const char *ad, const char *sinif, const char *kanit) {
    printf("%-30s%-10s%s\n", ad, sinif, kanit);
}

int main(void) {
    char tampon[64];
    int once;

    /* --- dil: ic ice bir blok icindeki otomatik degisken --- */
    int disarida = 1;
    {
        int icerde = 2;
        {
            int en_icerde = 3;
            snprintf(tampon, sizeof tampon,
                     "disarida %d, icerde %d, en_icerde %d, sayac farki %d",
                     disarida, icerde, en_icerde, fark());
            gozle("uc kat ic ice kapsam", "dil", tampon);
        }
    }

    /* --- cagiran: boyutu on kat buyuyen bir obek blogu yine cagirana ait --- */
    once = fark();
    enum { KUCUK = 4, BUYUK = 40 };
    int *kucuk_blok = say_ayir(KUCUK * sizeof *kucuk_blok);
    int *buyuk_blok = say_ayir(BUYUK * sizeof *buyuk_blok);
    int toplam = 0;
    if (kucuk_blok != NULL && buyuk_blok != NULL) {
        for (int i = 0; i < KUCUK; i++) {
            toplam += kucuk_blok[i] = i;
        }
        for (int i = 0; i < BUYUK; i++) {
            toplam += buyuk_blok[i] = i;
        }
    }
    say_birak(kucuk_blok);
    say_birak(buyuk_blok);
    snprintf(tampon, sizeof tampon, "toplam %d, sayac farki %d", toplam, fark() - once);
    gozle("kucuk ve buyuk blok", "cagiran", tampon);

    return 0;
}
```

```
uc kat ic ice kapsam          dil       disarida 1, icerde 2, en_icerde 3, sayac farki 0
kucuk ve buyuk blok           cagiran   toplam 786, sayac farki 0
```

**BE17.** `uc kat ic ice kapsam` gözleminde üç değişken üç ayrı `{ }` derinliğinde
bildirildi, ama üçü de otomatik bölgede ve üçü de sayacı hiç etkilemedi — kapsamın
derinliği, dil sınıfının geçerliliğini değiştirmiyor. `kucuk ve buyuk blok` gözlemi ise
boyutu on kat farklı iki öbek bloğunu (4 ve 40 eleman) yan yana ayırıp bırakıyor; sayaç
farkı yine **0**, ama bu kez iki ayrı `say_ayir`/`say_birak` çiftinin dengelenmesinden.
Bu, `Bölge Sahibi Belirler` bölümündeki iddiayı derinliğe ve boyuta karşı sınıyor: bir
bloğun otomatik mi öbek mi olduğunu belirleyen ne kapsamın kaç kat iç içe olduğu ne de
bloğun kaç bayt tuttuğu — belirleyen yalnız **hangi bildirimle** var olduğudur. `int
en_icerde` üç kapsam derinliğinde de olsa dil sınıfındandır; `say_ayir(40 * sizeof(int))`
tek bir çağrıda da olsa çağıran sınıfındandır.

## Aynı Sınıf, Farklı Kalıcılık

`dil` sınıfındaki hiçbir blok elle bırakılmaz — ama bu, `dil` sınıfının içindeki her
bölgenin **aynı** davrandığı anlamına gelmez. Otomatik bölge her çağrıda sıfırdan başlar,
statik bölge çağrılar arasında **kalıcıdır**. İkisi de sahiplik sorusuna aynı yanıtı verir
(sahip dil, bırakma çağrısı yok), ama ikisinin ömrü birbirinden tamamen farklıdır.

```c
// kalici.c — islev icindeki static degiskenin cagrilar arasinda kalici olmasi
#include <stdio.h>
#include "sayac.h"

static int fark(void) {
    return ayrilan_sayisi() - birakilan_sayisi();
}

static int sayac_tut(void) {
    static int cagri = 0;
    cagri++;
    return cagri;
}

static int yerel_sifirlanir(void) {
    int deger = 0;
    deger++;
    return deger;
}

int main(void) {
    char tampon[96];
    int once = fark();

    int birinci = sayac_tut();
    int ikinci = sayac_tut();
    int ucuncu = sayac_tut();

    int otomatik_birinci = yerel_sifirlanir();
    int otomatik_ikinci = yerel_sifirlanir();

    snprintf(tampon, sizeof tampon,
             "static cagrilar %d %d %d, otomatik cagrilar %d %d, sayac farki %d",
             birinci, ikinci, ucuncu, otomatik_birinci, otomatik_ikinci, fark() - once);
    printf("%-30s%s\n", "kalici ile sifirlanan", tampon);

    return 0;
}
```

```
kalici ile sifirlanan         static cagrilar 1 2 3, otomatik cagrilar 1 1, sayac farki 0
```

**BE18.** `sayac_tut` içindeki `cagri` değişkeni `static` bildirildiği için statik bölgede
durur ve üç çağrı boyunca aynı değeri **taşır**: 1, 2, 3. `yerel_sifirlanir` içindeki
`deger` ise otomatik bölgede, her çağrıda yeniden bildirilir ve `0`'dan başlar; iki çağrının
ikisi de **1** döndürüyor, çünkü ikinci çağrı birincinin bıraktığı yerden devam etmiyor.
Sayaç farkı hâlâ **0**, çünkü hiçbir öbek ayırması yapılmadı — bu ölçüm sahiplik sınıfını
değil, aynı sınıfın içindeki **ömür** farkını gösteriyor. `Bölge Sahibi Belirler, Sahip
Bölgeyi Belirlemez` bölümündeki kural burada da geçerli: `static` anahtar sözcüğü bir
değişkeni otomatik bölgeden statik bölgeye taşır ve bu taşıma, hâlâ hiçbir bırakma çağrısı
gerektirmeyen `dil` sınıfının içinde kalır — ama kalıcılığı kökten değiştirir.

## Sınırlayıcı Ölçüm

Bölgeler arasındaki sınırların nerede durduğu ve bir bloğun hangi hizalama değerine göre
yerleştiği çalışma zamanı ortamına bağlıdır; bu ders ne bir adres ne bir hizalama değeri
basıyor. `son - ilk` farkı **3** verdi — bu, iki adresin kendisi değil, aralarındaki
**eleman sayısı**dır ve bölge sınırından bağımsız, taşınabilir bir ölçüdür.

Otomatik bölgenin boyutu da sınırsız değildir — her çağrı çerçevesi, o bölgede sınırlı bir
yer kaplar ve iç içe kapsamlar (`uc kat ic ice kapsam` gözlemindeki gibi) ya da derin bir
özyineleme bu yeri tüketebilir. Bu sınırın aşılması tanımsız davranıştır (yaygın adıyla
**yığıt taşması**) ve bu ders, kursun geri kalanındaki tanımsız davranış kuralına uyarak bunu **hiç
koşturmuyor** — yalnız var olduğunu belirtiyor. Öbek bölgesinin sınırı ise farklı bir
biçimde görünür: `say_ayir` boyutu karşılayamadığında sessizce başarısız olmaz,
`malloc`'ın sözleşmesine uygun biçimde `NULL` döndürür ve bu ders boyunca her ayırma bu
dönüşle kontrol edildi (`kucuk_blok != NULL && buyuk_blok != NULL`). Otomatik bölgenin
taşması bir çökmeyle, öbek bölgesinin dolması bir `NULL` dönüşüyle kendini gösterir —
ikisi de bu bölgelerin **sınırsız olmadığının** kanıtı, ama biri denetlenebilir bir dönüş
değeri üretir, öteki üretmez.

## Özet

- Bellek dört bölgeye ayrılır: otomatik, statik, sabit veri ve öbek; bu dersin ölçtüğü
  bellek sınıfı **dil**dir.
- Otomatik ve statik bölgedeki bloklar hiçbir zaman elle bırakılmaz — sahibi dil, sayaç
  hiç kıpırdamaz.
- Öbek bölgesindeki bloklar `say_ayir`/`say_birak` ile dengelenir; sayaç farkı yine **0**
  çıkabilir ama bu kez ölçülüp dengelendiği için.
- Bölge, otomatik ve statik bellek için sahiplik sınıfını tek başına belirler; öbek
  bölgesinde sınıfı belirleyen bölge değil, sözleşmedir.
- Bölge sınırları ve hizalama değerleri ortama bağlıdır; bu derste basılmadı, M01/K01'e
  bırakıldı.

## Sonraki Adım

Dinamik Bellek konusu burada kapanıyor: dört sahiplik sınıfının (dil, çağıran, çağrılan, sahipsiz) her
biri en az bir ölçümle görüldü. Sıradaki konu, Sağlamlık, sözleşmenin **kırıldığı** anı konu alıyor — bir
kural yazılı olduğu hâlde bilerek çiğnendiğinde ne olduğunu, hangi durumların yalnız
düzyazıda tarif edilip hiç koşturulmadığını ve yanlarına hangi tanımlı karşılığın
koşturulduğunu.
