:: Akıllı Göstergeler (smart pointers)

murat335

New member
Göstergelerin (pointer) öğrenilmeleri kadar, hatasız kullanılmaları da zordur. Hatta bence C programcılarının hemen hemen her gün yaşadıkları bir güçlük doğrudan
göstergelerle ilgilidir:

PHP:
int foo0() { char * p0, *p1;    p0 = malloc(1);    if (birSeylerYap(p0))    {        free(p0);        return 1;    }    p1 = malloc(1);    baskaSeylerYap(p0, p1);    free(p1);    free(p0);    return 0;}
Yukarıdaki 'foo0' işlevinde bellek sızıntısı olmaması, programcının dikkatine kalmıştır. İşlevden çıkılan her noktada bellekten ayrılan bütün alanların geri verilmelerinin unutulmaması gerekir.

Bu kadar küçük bir işlevde sorunun büyüklüğü pek anlaşılmıyor olabilir. 'foo0'ın p2 adında bir göstergenin gösterdiği yeni bir bellek ayırması gerektiğini; hatta
işlevden çıkılabilecek yeni bir 'return' deyimi eklendiğini düşünün. Kod gittikçe daha karmaşık ve hatasız yazılması çok daha güç bir hale gelir. Her C programcısı bu tür işlevlerle karşılaşmıştır...

Daha ileri gitmeden önce, haksızlık olmasın diye, 'foo0'ı daha deneyimli bir programcının yazacağı şekliyle vereyim:

PHP:
int foo0_dahaIyi(){    char * p0;    p0 = malloc(1);    if (birSeylerYap(p0) == 0)    {        char * p1 = malloc(1);        baskaSeylerYap(p0, p1);        free(p1);        return 1;    }        free(p0);    return 0;}
Bu işlev bir öncekinden daha iyidir; çünkü

1) p1'in tanımı, kullanılmasının gerektiği ilk noktaya en yakın yere taşınmış durumdadır. Kodu okuyan kişilerin 'if' deyiminin içine bakmadan önce p1'den haberlerinin olması gerekmiyor.

2) Kaynak ayıran her bir deyime (malloc) karşılık kaynağı geri veren yalnızca bir tane deyim (free) görünüyor.

3) İşlev bu haliyle yeniden yapılandırmaya (refactorization) çok daha yatkındır. if deyiminin içindeki satırları oldukları gibi alıp başka bir işlevin içine kolayca taşıyabiliriz. Böylece kodun yapısı çok daha açık bir hale gelir.

Biraz konudan ayrılmış olsam da, buraya kadar söylemek istediklerim, C'de kaynak denetiminin programcıya bırakılmış olduğu ve doğru kullanımının programcının dikkatini
gerektirdiğidir.

Ayrıca söylediklerimin bellek denetimi ile kısıtlı olmadığına da dikkatinizi çekmek istiyorum. malloc satırlarını fopen'la, free satırlarını da fclose'la değiştirirseniz; sorun, bellek sızıntısı yerine kütük belirteci sızıntısı halini alır.

Bence bir C programcısı için C++'ın en çekici yanı, sınıfların kurucu ve bozucu işlevlerini kullanarak bütün bu kaynak sızıntılarından kurtulunuyor olmasıdır.

Biz insanlar her durumda hata yapmayı becerdiğimiz için, C++'ta da kaynak sızıntıları yaşarız. Ancak bunların çoğu, C++'ı C'den kalan alışkanlıklarımızla kullandığımız içindir. Hatta, eğer C++'ı C gibi kullanırsak, en azından kaynak sızıntıları açısından daha da kötü bir durumdayızdır. Bunun nedeni, C++'ın aykırı durum düzeneğidir (exception handling mechanism).

Aşağıdaki işlev, bir C programı içinde doğru yazılmış bir işlev olarak anılabilecekken, bir C++ programı içinde kullanıldığında hatalıdır

PHP:
void foo1()
{
    char * p = malloc(1);
    bar(p);
    free(p);
}
 

HTML

Üst