---
title: 'Bellek Hata Ayıklama Araçları'
source: 'https://academia.sh/tr/kurslar/c-bellek/bellek-hata-ayiklama-araclari'
course: "C'de Bellek ve İşaretçiler"
language: tr
updated: '2026-09-26T03:02:42+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir denetim noktasında ayrılan ile bırakılan sayısının karşılaştırılmasının bir aracın yaptığını nasıl modellediğini gösterir'
    - 'Dengeli bir ayırma dizisiyle dengesiz bir ayırma dizisinin aynı denetimden farklı sonuç aldığını ölçer'
    - 'Bir aracın adını, çıktısını ya da bayrağını anmadan yalnız yakalandi/yakalanmadi ikiliğiyle konuşur'
---

# Bellek Hata Ayıklama Araçları

Bir sızıntıyı elle sayaç tutarak bulmak gerçek bir programda mümkün değildir — bunu yapan bir araç çalıştırılır. Ders, kursun baştan beri kullandığı sayaçlı sarmalayıcının, böyle bir aracın yaptığı tek şeyi zaten modellediğini gösteriyor: her ayırmanın karşılığında bir bırakma var mı, yok mu.

Önceki ders bir sızıntının hiçbir hata mesajı ya da çökme üretmediğini, yalnız sayaç
farkıyla göründüğünü gösterdi. Gerçek bir programda kimse elle `ayrilan_sayisi()` ile
`birakilan_sayisi()`yi karşılaştırmaz — bunu yapan **bir araç** çalıştırılır. Bu dersin
konusu böyle bir aracın kendisi değil; konusu, o aracın **yaptığı tek şeyin** ne olduğu.
Kursun baştan beri kullandığı `sayac.c`, aslında bunu birinci dersten beri modelliyordu.

Bu, önceki dersin doğal devamı. `Bellek Sızıntıları` dersi sahipsiz sınıfın iki türünü
gösterdi ve ikisini de elle tutulan bir sayaç farkıyla ölçtü. Ama gerçek bir programda
kimse `main` içine `ayrilan_sayisi() - birakilan_sayisi()` satırı yazıp sonucu elle
okumaz; program büyüdükçe, yüzlerce ayırma çağrısı arasında hangi birinin karşılıksız
kaldığını elle izlemek pratik değildir. Bu yüzden bu işi otomatikleştiren bir katman
devreye girer — ve bu dersin tek iddiası, o katmanın yaptığı şeyin, kursun baştan beri
kullandığı sayaçlı sarmalayıcıdan **daha karmaşık bir fikre dayanmadığıdır.**

## Bir Denetim Noktası Neyi Karşılaştırır

Bir aracın yaptığı, özünde tek bir işlemdir: programın belirli bir noktasında (çoğunlukla
çıkışında) o ana kadar yapılan her ayırma çağrısının karşılığında bir bırakma çağrısı olup
olmadığını sayar. Karşılık varsa denetim **temiz** çıkar; yoksa, karşılığı bulunamayan her
blok için bir bulgu bildirilir. Bu kursta bu karşılaştırma, `sayac.c`nin tuttuğu iki sayının
farkıdır — `ayrilan_sayisi()` eksi `birakilan_sayisi()`. Fark sıfırsa **yakalanmadi**, sıfır
değilse **yakalandi**.

```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;
}
```

**BE12.** `sayac.c` bu kursun ilk dersinden beri değişmeden duruyor ve hiçbir yerde "araç"
sözcüğünü taşımıyor — yalnız iki sayaç ve dört işlev. Ama yaptığı şey, bir denetim
noktasında ayrılanla bırakılanı karşılaştırmaktan ibaret; bu, gerçek bir aracın yaptığı işin
küçültülmüş ve elle kurulmuş hâlidir. Fark, gerçek bir araç bu karşılaştırmayı programın
kaynak koduna hiç dokunmadan yapar; burada aynı karşılaştırma `sayac.c`nin içine **elle**
yazıldı.

## Dengeli ve Dengesiz Dizi

```c
// denetim.c — bir denetim noktasinin dengeli ve dengesiz diziyi ayirt etmesi
#include <stdio.h>
#include "sayac.h"

static const char *denetle(int fark) {
    return fark != 0 ? "yakalandi" : "yakalanmadi";
}

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

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

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

    /* --- dengeli dizi: her ayirmanin karsiligi var --- */
    once = ayrilan_sayisi() - birakilan_sayisi();
    int *birinci = say_ayir(2 * sizeof *birinci);
    int *ikinci = say_ayir(3 * sizeof *ikinci);
    say_birak(birinci);
    say_birak(ikinci);
    fark_sonra = (ayrilan_sayisi() - birakilan_sayisi()) - once;
    snprintf(tampon, sizeof tampon, "denetim noktasi: %s", denetle(fark_sonra));
    gozle("dengeli dizi", tampon);

    /* --- dengesiz dizi: bir ayirmanin karsiligi yok --- */
    once = ayrilan_sayisi() - birakilan_sayisi();
    int *ucuncu = say_ayir(2 * sizeof *ucuncu);
    int *dorduncu = say_ayir(3 * sizeof *dorduncu);
    say_birak(ucuncu);
    /* dorduncu bilerek birakilmiyor: dengesiz dizi burada kuruluyor */
    fark_sonra = (ayrilan_sayisi() - birakilan_sayisi()) - once;
    snprintf(tampon, sizeof tampon, "denetim noktasi: %s", denetle(fark_sonra));
    gozle("dengesiz dizi", tampon);

    say_birak(dorduncu);
    return 0;
}
```

```
gozlem                        kanit
dengeli dizi                  denetim noktasi: yakalanmadi
dengesiz dizi                 denetim noktasi: yakalandi
```

**BE13.** `dengeli dizi` gözleminde iki ayırmanın ikisi de kendi bloğu içinde bırakıldı;
denetim noktasındaki fark **0** ve sonuç **yakalanmadi**. `dengesiz dizi` gözleminde ise
`dorduncu` o denetim noktasına gelene kadar bırakılmadı — kod bunu kendisi, yorum satırıyla
işaretleyerek yaptı, çünkü bir aracın gerçekte ne bulduğunu göstermenin tek tanımlı yolu bu.
Fark **1**e çıktı ve sonuç **yakalandi**. Denetim noktasından sonra `dorduncu` yine de
bırakıldı — ders, tanımlı olmayan bir durumu (programı sızıntılı bitirmeyi) arkasında
bırakmıyor.

## Üç Ardışık Denetim Noktası

Önceki bölümdeki iki gözlem birbirinden **bağımsız** iki dizi kurdu — her biri kendi
`once` değerinden başladı. Gerçek bir programda denetim noktaları böyle yalıtılmış
durmaz; art arda gelir ve her biri yalnız **kendisinden önceki** noktadan bu yana olan
aralığı görür. Bu, bir sızıntının hangi denetim noktasında yakalandığının, sızıntının
nerede oluştuğuyla aynı yer olduğunu gösterir — ne bir önceki noktada, ne bir sonrakinde.

```c
// ardisik.c — sizintinin tam olustugu denetim noktasinda yakalanmasi
#include <stdio.h>
#include "sayac.h"

static const char *denetle(int fark) {
    return fark != 0 ? "yakalandi" : "yakalanmadi";
}

int main(void) {
    char tampon[64];
    int nokta_once = ayrilan_sayisi() - birakilan_sayisi();

    /* --- birinci nokta: temiz bir ayirma-birakma cifti --- */
    int *a = say_ayir(sizeof *a);
    say_birak(a);
    int fark1 = (ayrilan_sayisi() - birakilan_sayisi()) - nokta_once;
    snprintf(tampon, sizeof tampon, "nokta 1: %s", denetle(fark1));
    printf("%-30s%s\n", "ardisik denetim", tampon);
    nokta_once = ayrilan_sayisi() - birakilan_sayisi();

    /* --- ikinci nokta: bilerek birakilmayan bir blok --- */
    int *b = say_ayir(sizeof *b);
    int fark2 = (ayrilan_sayisi() - birakilan_sayisi()) - nokta_once;
    snprintf(tampon, sizeof tampon, "nokta 2: %s", denetle(fark2));
    printf("%-30s%s\n", "ardisik denetim", tampon);
    nokta_once = ayrilan_sayisi() - birakilan_sayisi();

    /* --- ucuncu nokta: b'den bagimsiz, kendi icinde dengeli yeni bir cift --- */
    int *c = say_ayir(sizeof *c);
    say_birak(c);
    int fark3 = (ayrilan_sayisi() - birakilan_sayisi()) - nokta_once;
    snprintf(tampon, sizeof tampon, "nokta 3: %s", denetle(fark3));
    printf("%-30s%s\n", "ardisik denetim", tampon);

    say_birak(b);
    return 0;
}
```

```
ardisik denetim               nokta 1: yakalanmadi
ardisik denetim               nokta 2: yakalandi
ardisik denetim               nokta 3: yakalanmadi
```

**BE14.** `b` ikinci noktada ayrılıp o noktaya kadar hiç bırakılmadı, bu yüzden
**nokta 2** sonucu `yakalandi`. Üçüncü nokta ise `b`'den tamamen bağımsız, kendi içinde
dengeli yeni bir çift (`c`) kuruyor — kendi aralığında bir ayırmanın karşılığında bir
bırakma var, bu yüzden **nokta 3: yakalanmadi**. `b`'nin sızıntısı ikinci noktadan sonra
hiçbir yerde yeniden raporlanmıyor; üçüncü nokta onu bir daha saymıyor, çünkü her nokta
yalnızca **kendi aralığında** karşılıksız kalan ayırmaları görür, daha önce zaten
raporlanmış bir aralığı tekrar taramaz. Bu üç sonuç birlikte önemli bir şeyi gösteriyor:
bir sızıntı gerçek zamanda tam **hangi aralıkta** oluştuysa, denetim de tam o aralıkta
yakalar — ne bir önceki noktada (henüz ayrılmamıştı), ne bir sonraki noktada (o aralığın
konusu değil). `b` sonunda yine `say_birak` ile bırakılıyor, ama bu bırakma hiçbir
noktanın ölçtüğü aralığın içinde değil — kod yalnız programı sızıntılı bitirmemek için
bunu yapıyor, denetim anlatısının bir parçası olarak değil.

## Gecikmiş Bir Bırakma Yeni Bir Sızıntıyı Maskeleyebilir

Üç ardışık noktanın gösterdiği düzenek bir varsayıma dayanıyordu: her aralıktaki ayırma ve
bırakma çağrıları o aralığın **kendi olayları**. Ama gerçek bir programda bir blok, bir
denetim noktasında ayrılıp başka bir noktada bırakılabilir — ve bu, sayaç farkının aynı
aralıkta oluşan **başka** bir sızıntıyı sayısal olarak dengeleyip gizlemesine yol açabilir.
Bu, sayaç tabanlı denetimin bir kusuru değil, **sınırıdır**: denetim yalnız net farkı görür,
hangi bloğun hangi olaya ait olduğunu görmez.

```c
// gecikmis.c — onceki araliktan tasinan bir birakmanin yeni bir sizintiyi maskelemesi
#include <stdio.h>
#include "sayac.h"

static const char *denetle(int fark) {
    return fark != 0 ? "yakalandi" : "yakalanmadi";
}

int main(void) {
    char tampon[64];
    int nokta_once = ayrilan_sayisi() - birakilan_sayisi();

    /* --- A noktasi: d ayriliyor, bu araliktan hic birakilmiyor --- */
    int *d = say_ayir(sizeof *d);
    int farkA = (ayrilan_sayisi() - birakilan_sayisi()) - nokta_once;
    snprintf(tampon, sizeof tampon, "nokta A: %s", denetle(farkA));
    printf("%-30s%s\n", "gecikmis birakma", tampon);
    nokta_once = ayrilan_sayisi() - birakilan_sayisi();

    /* --- B noktasi: yeni bir sizinti (e) olusuyor, ama d de burada birakiliyor --- */
    int *e = say_ayir(sizeof *e);
    say_birak(d);
    int farkB = (ayrilan_sayisi() - birakilan_sayisi()) - nokta_once;
    snprintf(tampon, sizeof tampon, "nokta B: %s", denetle(farkB));
    printf("%-30s%s\n", "gecikmis birakma", tampon);

    say_birak(e);
    return 0;
}
```

```
gecikmis birakma              nokta A: yakalandi
gecikmis birakma              nokta B: yakalanmadi
```

**BE15.** A noktası, `d`'nin o aralıkta bırakılmadığını doğru biçimde `yakalandi` olarak
bildiriyor — tıpkı önceki bölümdeki nokta 2 gibi. B noktasında ise iki şey aynı anda
oluyor: `e` yeni ayrılıyor ve **hiç bırakılmıyor** bu aralıkta, üstelik `d` de (önceki
aralıktan kalan borç) tam bu aralıkta bırakılıyor. Sayaç farkı bu iki olayı ayrı ayrı
görmüyor, yalnız toplamlarını görüyor: `+1` (yeni ayrılan `e`) ile `-1` (geç bırakılan
`d`) birbirini götürüyor ve `farkB` **0** çıkıyor — sonuç **yakalanmadi**, oysa bu aralıkta
gerçekten yeni bir blok (`e`) sızdırılmış durumda. `e` yalnızca `main`'in sonunda, hiçbir
denetim noktasının ölçmediği bir yerde bırakılıyor. Bu, bir sayaç farkının **sıfır**
olmasının, o aralıkta hiçbir sorun olmadığı anlamına gelmediğini gösteriyor — yalnız
ayrılan ile bırakılanın **sayıca** eşitlendiği anlamına gelir. Gerçek araçların çoğu bu
sınırı, yalnız sayıyı değil her bloğun kendi kimliğini (hangi satırda ayrıldığını) izleyerek
aşar; bu kurs böyle bir kimlik izlemiyor, çünkü konusu aracın kendisi değil, aracın
dayandığı temel fikir.

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

Bir denetim noktası yalnız **sayar** — hangi bloğun hangi satırda ayrıldığını, o bloğun
programın hangi bölümüne ait olduğunu, ya da bloğun içeriğinin ne olduğunu bilmez. Bildiği
tek şey, karşılığı bulunamayan ayırma çağrısının **sayısıdır**. Bu yüzden bu kursta bir
aracın verdiği yanıt yalnız iki değerden biri olarak yazılıyor: **yakalandi** ya da
**yakalanmadi**. Bu ikilik dışında hiçbir çıktı biçimi, hiçbir bayrak, hiçbir araç adı bu
derste geçmiyor — çünkü hangi aracın hangi çıktıyı ürettiği ortama bağlıdır, ölçülen
düzenek değildir.

Bir aracın **bulamadığı** şey de önemlidir: bir işaretçinin üzerine yazılmadan önce eski
değerinin bir yere kaydedilip kaydedilmediğini, ya da bir bloğun sahiplik sözleşmesinin
`sahip.h`deki yorumla uyuşup uyuşmadığını bir denetim noktası bilemez — bunlar kaynak
kodun okunmasını gerektirir. Denetim noktası yalnız **sayının kendisini** doğrular; sayının
neden o değere ulaştığını açıklamaz.

Araç adının ve çıktı biçiminin bu derste hiç geçmemesinin tek nedeni özen değil; bir
gerekliliktir. Aynı denetim fikri, farklı ortamlarda farklı araçlarla, farklı çıktı
biçimleriyle uygulanabilir — bazısı programı ayrı bir süreç içinde çalıştırır, bazısı
ayırma işlevlerinin kendisini değiştirir, bazısı yalnız çıkıştaki özeti yazar. Bu kurs
hangi ortamda koşacağını bilemeyeceği için, ölçtüğü şeyi ortamdan bağımsız tek bir
düzeneğe indirgiyor: bir sayı ve o sayının sıfır olup olmadığı. `yakalandi` ile
`yakalanmadi` bu yüzden bir basitleştirme değil, dersin **gerçek konusunun** kendisidir.

## Özet

- Bir bellek hata ayıklama aracının yaptığı tek şey, bir denetim noktasında ayrılan ile
  bırakılan sayısını karşılaştırmaktır; bu dersin ölçtüğü bellek sınıfı yine
  **sahipsiz**dır.
- `sayac.c`, kursun ilk dersinden beri bu karşılaştırmayı elle yapıyordu; bu ders bunu
  ilk kez adlandırdı.
- Dengeli bir dizide denetim noktası **yakalanmadi**, dengesiz bir dizide **yakalandi**
  sonucunu verdi; ikisi dışında üçüncü bir sonuç yok.
- Hiçbir araç adı, çıktı biçimi ya da bayrak bu derste geçmedi — bunlar ortama bağlıdır,
  ölçülen düzenek değildir.

## Sonraki Adım

Bu ders belleği **modüller arasında** dolaşırken izledi — ayrılan bir bloğun kimin elinde
olduğu, denetim noktasına kadar nasıl değiştiği. Dinamik Bellek konusunun son dersi ise geri, en başa
dönüyor: dört `dil` gözlemi ile `ayir ve birak` gözlemini yan yana koyup, bir bloğun
**hangi bölgede** durduğunun — otomatik, statik ya da dinamik — sahiplik sorusuyla nasıl
örtüştüğünü gösteriyor.
