Özgür Bellek Ayırma
Önceki Yazılım Verisine Saklama Alanı Ayrılması Sonraki
Özgür Bellek Ayırma
En çok kullanılan özdevimli bellek ayırma oluşumu malloc işlevidir. Bu işlevi kullanarak istediğiniz zaman istediğiniz boyutta bellek bloğu ayırabilir, istediğinizde büyütebilir, küçültebilir ve ihtiyacınız kalmadığında serbest bırakabilir ya da hiç serbest bırakmayabilirsiniz.
Özdevimli Olarak Basit Bellek Ayırma
Bir bellek bloğunu ayırmak için malloc çağrılır. Bu işlev stdlib.h başlık dosyasında bildirilmiştir.
void *malloc
(size_t boyut)
işlev
Bu işlev boyut bayt uzunlukta yeni bir bellek bloğu ayırabilirse bu bloğa bir gösterici ile döner yoksa bir boş gösterici ile döner.
Bloğun içi tanımsızdır; içeriğini kendiniz ilklendirmelisiniz (ya da calloc kullanın). Bkz. Temizlenmiş Bellek Ayırma.
Normalde blok içinde saklamak istediğiniz nesnenin türüne bir gösterici olan değere tür dönüşümü uygulamalısınız. Aşağıda bu yönteme ilişkin bir örnek vardır. Burada blok, memset kütüphane işlevi kullanılarak sıfırlarla ilklendirilmektedir (Bkz. Kopyalama ve Birleştirme):
struct foo *ptr;
…
ptr = (struct foo *) malloc (sizeof (struct foo));
if (ptr == 0) abort ();
memset (ptr, 0, sizeof (struct foo));
ISO C void * türünü gerektiğinde özdevinimli olarak başka bir gösterici türüne dönüştürebildiğinden, malloc işlevinin sonucunu bir tür dönüşümü yapmaksızın bir gösterici değişkeninde saklayabilirsiniz. Ancak kodu geleneksel C ile çalıştıracaksanız ya da atama işleci kullanmayacaksanız tür dönüşümü yapmanız gerekir.
Bir dizge için yer ayırırken malloc işlevine belirteceğiniz argümanın değeri, dizgenin uzunluğu artı bir olmalıdır. Bu, dizgenin bir NULL karakteri ile sonlandırılması ve NULL karakterinin dizgenin uzunluğundan sayılmamasından dolayıdır. Örnek:
char *ptr;
…
ptr = (char *) malloc (length + 1);
Bu konu hakkında daha ayrıntılı bilgi edinmek için Dizgelerle İlgili Kavramlar bölümüne bakınız.
malloc Örnekleri
Ayrılabilecek bellek yoksa malloc bir boş gösterici ile döner. malloc işlevini her çağırışınızda dönen değere bakmalısınız. malloc'u çağıran, bir boş gösterge döndüğünde hatayı bildiren ve sadece sıfırdan farklı bir değerle dönen bir yardımcı işlev yazabilirsiniz. Bu yöntem teamülen xmalloc olarak bilinir ve aşağıdaki gibi gerçeklenir:
void * xmalloc (size_t size)
{
  register void *value = malloc (size);
  if (value == 0)
    fatal ("sanal bellek tükendi");
  return value;
}
Aşağıda ise malloc kullanılan (xmalloc yoluyla) gerçek bir örnek vardır. savestring işlevi bir karakter dizisini yeni ayrılan null sonlandırmalı dizgeye kopyalamaktadır:
char * savestring (const char *ptr, size_t len)
{
  register char *value = (char *) xmalloc (len + 1);
  value[len] = '\0';
  return (char *) memcpy (value, ptr, len);
}
malloc'un size verdiği blok her türden veriyi tutabilir. GNU sisteminin bellek yönetimine göre, bir çok sistemde adres sekizin katlarıdır, 64 bitlik sistemlerde ise onaltının katlarıdır. Daha yüksek sınırlar (sayfa seviyesi) gerekliyse memalign, posix_memalign veya valloc kullanılır (Bkz. Bellek Bloklarının Hizalanarak Ayrılması).
Not
Bir malloc çağrısı ile ayrılan bloğun sonuna başka birşeyler için kullanılmak üzere bellek eklenmesi gerekebilir. Daha önce ayrılmış bir bloğu büyütmek için malloc kullanmaya çalışırsanız ya önceki ayrılan bloğu ya da yenisini bozmanız mümkündür. Ayrılmış belleği sonradan büyütmek isterseniz realloc işlevini kullanın (Bkz. Bir Bellek Bloğunun Boyutunun Değiştirilmesi).
malloc ile Ayrılan Belleğin Serbest Bırakılması
malloc ile ayırdığınız bir bloğa ihtiyacınız kalmadığında, ayrılan bloğu tekrar kullanılabilir hale getirmek için free ile serbest bırakmalısınız. free işlevi stdlib.h başlık dosyasında bildirilmiştir.
void free
(void *gösterici)
işlev
free işlevi gösterici ile erişilen bellek bloğunu serbest bırakır.
void cfree
(void *gösterici)
işlev
Bu işlev free ile aynı işi yapar. İşlev SunOS ile geriye uyumluluk adına kütüphaneye dahil edilmiştir. Bu işlevi değil free işlevini kullanmalısınız.
Bir bloğun serbest bırakılması bloğun içeriğini değiştirir. Bir bloğu serbest bıraktıktan sonra bloğun içindeki bir veriye ulaşabileceğinizi sanmayın (örneğin bir blok zincirindeki sonraki bloğa bir gösterici belirterek.) Bir bloğu serbest bırakmadan önce içinde kullanacağınız bir bilgi varsa kopyalamayı unutmayın. Aşağıdaki örnekte bir zincirdeki blokların tümü sırayla serbest bırakılmaktadır:
struct chain
  {
    struct chain *next;
    char *name;
  }

void
free_chain (struct chain *chain)
{
  while (chain != 0)
    {
      struct chain *next = chain->next;
      free (chain->name);
      free (chain);
      chain = next;
    }
}
free işlevi bellek alanını uzun dönemde işletim sistemine döndürür ve süreci küçültür. Sistem genelinde ise, bellek alanını yeniden kullanılmak üzere serbest bırakır ve daha sonraki malloc çağrılarını mümkün kılar. Kısa dönemde ise, serbest bırakılan alan malloc tarafından süreç dahilinde kullanılmak üzere bir serbest bırakılanlar listesinin parçası olarak bekletilir.
Yazılımın çalışması sona erdiğinde blokların bırakılması gerekmez. Çünkü süreç sonlandığında sürece ayrılan tüm alan sisteme geri verilir.
Bir Bellek Bloğunun Boyutunun Değiştirilmesi
Çoğunlukla bir bellek bloğunu kullanmaya başlarken ihtiyacınız olacak bellek miktarını bilemez ve yaklaşık bir boyut ile bloğu ayırırsınız. Örneğin, blok bir dosyadan okunan satırı tutan bir tampon olabilir ve bir satır için yeterli olan tamponunuz başka bir satır için yetersiz kalabilir.
realloc işlevini çağırarak bloğu uzatabilirsiniz. Bu işlev stdlib.h başlık dosyasında bildirilmiştir.
void *realloc
(void  *gösterici,
 size_t yeniboyut)
işlev
realloc işlevi gösterici ile erişilen bloğun boyunu yeniboyut ile belirtilen değere ayarlar.
Bloktan sora gelen alan kullanılabilir olsa da realloc işlevi bloğu daha fazla serbest alanın bulunduğu yeni bir adrese kopyalamayı gerekli bulabilir. realloc işlevi bloğun yeni adresi ile döner. Blokun taşınması gerekirse, realloc eski içeriği kopyalar.
realloc işlevine gösterici için bir boş gösterici belirtirseniz, işlev, malloc (newsize) çağrılmış gibi davranır. Bu kullanışlı olabilirse de, ISO C öncesi C gerçeklemeleri bu davranışı desteklemeyebilir ve büyük ihtimalle realloc boş bir gösterici ile çökebilir.
realloc işlevi daha büyük blok oluşturamazsa tıpkı malloc işlevi gibi bir boş gösterici ile döner. Bu durum oluştuğunda eski bloka dokunulmaz; değiştirilmez ve başka bir konuma taşınmaz.
Çoğu durumda realloc başarısız olduğunda eski bloğa ne olduğunun fazla bir önemi kalmaz. Çünkü uygulama yazılımı bellek yetmediğinde çalışmasını sürdüremez ve yapacak tek şey kalır: bir ölümcül hata iletisi ile kendini sonlandırmak. Çoğunlukla bu durum için bir yordam yazılır. malloc için benzer yordama xmalloc dendiği gibi realloc için olanına da xrealloc denir:
void * xrealloc (void *ptr, size_t size)
{
  register void *value = realloc (ptr, size);
  if (value == 0)
    fatal ("Sanal bellek tükendi");
  return value;
}
realloc işlevini bloğu küçültmek için de kullanabilirsiniz. Bu genelde daha küçük belleğin yeterli olduğu durumlarda bir bellek tıkanıklığı varsa ayrılan fazla belleği serbest bırakmak için yapılır. Bazı ayırma gerçeklemelerinde bir bloğun küçültülmesi bazı durumlarda kopyalanmasını zorunlu kılabilir ve kullanılabilir bir bellek yoksa işlev başarısız olabilir.
realloc işlevine belirtilen yeni boyut eskisi ile aynıysa işlev hiçbir değişiklik yapmaz ve verdiğiniz adresi geri döndürür.
Temizlenmiş Bellek Ayırma
calloc işlevi belleği ayırdıktan sonra içeriğini sıfırlarla doldurarak temizler. Bu işlev stdlib.h başlık dosyasında bildirilmiştir.
void *calloc
(size_t elmsayısı,
 size_t elmboyu)
işlev
Bu işlev boyu elmboyu olan elmtsayısı sayıda eleman içeren bir blok ayırır. Bu içerik calloc dönmeden önce sıfırlarla doldurulur.
calloc işlevini aşağıdaki gibi tanımlayabilirsiniz:
void * calloc (size_t count, size_t eltsize)
{
  size_t size = count * eltsize;
  void *value = malloc (size);
  if (value != 0)
    memset (value, 0, size);
  return value;
}
Ancak genelde, calloc işlevinin dahili olarak malloc işlevini çağıracağının garantisi yoktur. Bu nedenle, bir uygulama C kütüphanesi dışında kendi malloc, realloc ve free işlevlerini sağlıyorsa, calloc işlevini de mutlaka tanımlamalıdır.
malloc için Yeterlik Kaygıları
Diğer sürümlerin aksine GNU C kütüphanesindeki malloc işlevi ayırdığı belleğin boyunu ikinin kuvvetlerine ayarlamaz, dolayısıyla istenenden daha küçük ya da daha büyük bir bellek ayırmaz. Komşu bellek parçaları boyutlarına bakılmaksızın bir free üzerinden tek parça yapılabilir. Bu, yüksek belleğin küçük kesintili bloklar haline gelmesine sebep olmadan, gerçeklemeyi ayırma kalıplarının her türü için elverişli yapar.
Çok büyük bloklar (bir sayfadan büyük) bu gerçeklenimce mmap işlevi ile (anonim veya /dev/zero üzerinden) ayrılır. Serbest bırakıldıkları anda parçaların sisteme döndürülmesi büyük yarar sağlar. Bu bakımdan, daha küçük bir bloktan büyütülürken iki işlem arasında blok kilitli hale gelemez ve hatta free çağrısından sonra blok belleği boşalır. mmap için kullanılacak boyut eşiği mallopt ile ayarlanabilir. Ayrıca mmap kullanımı tamamen iptal de edilebilir.
Bellek Bloklarının Hizalanarak Ayrılması
Bir blok için malloc tarafından döndürülen adres GNU sistemlerinde daima sekizin katlarıdır (64 bitlik sistemlerde onaltının katlarıdır). Bir bloğun daha büyük adres adımları (adım boyu ikinin kuvveti olmalı) ile adreslenmesini isterseniz memalign, posix_memalign veya valloc işlevlerini kullanmalısınız. memalign işlevi malloc.h, posix_memalign işlevi ise stdlib.h başlık dosyasında bildirilmiştir.
GNU kütüphanesi ile, memalign, posix_memalign veya valloc ile dönen blokları serbest bırakmak için free kullanılır. Bu BSD ile çalışmaz, çünkü BSD bu tür blokları serbest bırakacak bir yol sağlamaz.
void *memalign
(size_t adımboyu,
 size_t boyut)
işlev
memalign işlevi boyut uzunluktaki bloğu adımboyunun katları olan adreslerden birinde ayırır ve bloğun adresi ile döner. adımboyu ikinin kuvveti olan bir değer olmalıdır. İşlev büyük miktarda (sayfa kadar veya fazlası) bellek ayırmak için kullanılır.
int posix_memalign
(void **gösterici,
 size_t adımboyu,
 size_t boyut)
işlev
posix_memalign işlevi memalign işlevine benzer şekilde adımboyunun katlarına hizalayarak boyut uzunluktaki bir tampon ayırır. Ancak işlev adımboyu parametresinde bir özelliğin varlığına bağımlıdır: değer, sizeof (void *) değerinin ikinin kuvveti katı olmalıdır.
İşlev, belleği ayırmada başarılı olursa, ayrılan belleğin göstericisi *gösterici'ye atanır ve işlev sıfır değeriyle döner. Aksi takdirde sorunu belirten bir hata değeri ile döner.
Bu işlev POSIX 1003.1d içinde geçer.
void *valloc
(size_t boyut)
işlev
valloc işlevi sayfa boyunda adresleme ile boyut uzunlukta blok ayırır. memalign kullanılarak aşağıdaki gibi gerçeklenebilir:
void * valloc (size_t size)
{
  return memalign (getpagesize (), size);
}
Bellek altsistemi hakkında ayrıntılı bilgi Bellek Parametrelerinin Sorgulanması bölümünde bulunabilir.
Ayarlanabilir Malloc Parametreleri
Özdevimli bellek ayırma ile ilgili bazı parametreleri mallopt ile ayarlayabilirsiniz. Bu işlev bir genel SVID/XPG arayüzüdür ve malloc.h başlık dosyasında bildirilmiştir.
int mallopt
(int param,
 int değer)
işlev
mallopt işlevi çağrılırken ayarlanacak parametre param ile, değeri ise değer ile belirtilir. malloc.h başlık dosyasında tanımlı param seçenekleri şunlardır:
M_TRIM_THRESHOLD
Belleğin sisteme döndürülmesi sırasında bir negatif argüman ile sbrk'in çağrılmasına sağlayacak en tepedeki serbest bırakılabilir parçanın mümkün en küçük boyudur (bayt cinsinden).
M_TOP_PAD
Bu parametre bir sbrk çağrısı gerektiğinde sistemden sağlanacak fazladan belleğin miktarını belirler. Ayrıca, bir negatif argümanla sbrk çağırarak yığın belleğin (heap) küçültülmesi sırasında tutulan baytların sayısını belirtir. Bu, yığın bellekte gerekli histerezisi oluşturur ve örneğin aşırı miktarlarda sistem çağrılarını engelleyebilir.
M_MMAP_THRESHOLD
Bu değerden daha büyük parçalar mmap sistem çağrısı kullanılarak normal yığın belleğin dışında ayrılır. Bu yol, bu parçaların free üzerinden sisteme döndürülebilirliğini garanti eder. Bu eşik değerden daha küçük istekler hala mmap üzerinden ayrılabilir.
M_MMAP_MAX
mmap ile ayrılabilecek parçaların mümkün en büyük sayısıdır. Bu parametreye sıfır değeri atanarak mmap kullanımı iptal edilebilir.
Yığın Bellek Tutarlılık Denetimi
mcheck işlevini kullanarak özdevimli ayrılan belleğin tutarlılığının malloc tarafından denetlenmesini isteyebilirsiniz. Bu işlev bir GNU oluşumudur ve mcheck.h başlık dosyasında bildirilmiştir.
int mcheck
(void (*çıkış_işlevi) (enum mcheck_status durum))
işlev
mcheck işlevinin çağrılması malloc'a arasıra tutarlılık denetimi yapmasını söyler. Bu sayede malloc ile ayrılan belleği aşan yazma işlemleri yakalanır.
çıkış_işlevi argümanı ile bir tutarsızlık bulunduğunda çağrılacak işlev belirtilir. Burada bir boş gösterici belirtirseniz, mcheck işlevi bir ileti basarak öntanımlı olan abort işlevini çağırır. Sizin tarafınızdan sağlanan işlev saptanan tutarsızlık türünün belirtildiği bir argümanla çağrılır. Tutarsızlık türleri aşağıda açıklanmıştır.
malloc ile bellek ayırma yaptıktan sonra tutarlılık denetimini başlatmak için kimi zaman çok geç kalınabilir. Bu durumda mcheck hiçbir şey yapmaz. Eğer çağrı için çok geç kalınmışsa mcheck -1 ile aksi takdirde 0 ile döner.
mcheck işlevini yeterince erken çağırmanın en kolay yolu, yazılımınızı ilintilerken -lmcheck seçeneğini kullanmaktır. Böylece yazılımınızın kaynak kodunu değiştirmeniz gerekmez. Başka bir yol da, yazılımınızı her başlattığınızda bir mcheck çağrısı girecek bir hata ayıklayıcı kullanmaktır. Örneğin, aşağıdaki gibi yazılımınızı her başlattığınızda gdb komutları özdevinimli olarak mcheck'i çağıracaktır.
(gdb) break main
Breakpoint 1, main (argc=2, argv=0xbffff964) at whatever.c:10
(gdb) command 1
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>call mcheck(0)
>continue
>end
(gdb) …
mcheck işlevinin malloc işlevinden önce çağrılması gerektiğinden bu kod sadece malloc işlevini çağıran nesnelerde böyle bir ilklendirme işlevi yoksa çalışır.
enum mcheck_status mprobe
(void *gösterici)
işlev
mprobe işlevi ile bir ayrılmış blok üzerinde tutarlılık denetimi yapılmasını doğrudan doğruya isteyebilirsiniz. Bu denetimin arasıra yapılması için zaten yazılımın hemen başlarında mcheck çağrısı yapmış olmalısınız; mprobe çağrısı ile çağrı sırasında bir ek tutarlılık denetimi yapılmasını isteyebilirsiniz.
gösterici, bir malloc ya da realloc işlevinden dönmüş bir gösterici olmalıdır. mprobe işlevi ne tür bir tutarsızlık olduğunu belirten bir değer ile döner. Bu değerler aşağıda açıklanmıştır.
enum mcheck_status
veri türü
Bu numaralı tür, bir ayrılmış blokta saptanan tutarsızlığın çeşidini açıklar. Olası değerler:
MCHECK_DISABLED
mcheck ilk ayırma işleminden önce çağrılmamış. Hiçbir tutarlılık denetimi yapılamaz.
MCHECK_OK
Bir tutarsızlık yok.
MCHECK_HEAD
Bloğun öncesi değiştirildi. Bu durum genellikle, bir dizi indisi ya da bir göstericinin bloğun başlangıcındaki değerinin altına indirildiğinde ortaya çıkar.
MCHECK_TAIL
Bloktan sonrası değiştirildi. Bu durum genellikle, bir dizi indisi ya da bir göstericinin değeri blok aşılacak kadar arttırıldığında ortaya çıkar.
MCHECK_FREE
Blok zaten serbest bırakılmış.
Diğer bir denetim başlatma yöntemi, malloc, realloc ve free kullanımında yazılım hatalarına karşı bir önlem olarak MALLOC_CHECK_ ortam değişkeninin belirtilmesidir. MALLOC_CHECK_ bir denetim yapılması için belirtilmişse, çifte free çağrısı veya bir tek baytlık taşma gibi basit hatalara tolerans gösteren (daha az tutarlı) özel bir gerçekleme kullanılır. Bu tür hatalara karşı bir koruma olmadığından bellek artıkları olabileceği dikkate alınmalıdır.
MALLOC_CHECK_ için 0 değeri kullanılırsa, bir yığın bellek bozulması gözardı edilecektir. 1 kullanılırsa, standart hataya tanımlayıcı bir ileti basılır. 2 olması durumunda ise hemen abort çağrılır. Bu son durum genellikle hatanın hemen ardından bir çökmenin kaçınılmaz olduğu dolayısıyla hatanın geriye doğru izlenebilirliğinin çok zor olduğu durumlarda kullanışlıdır.
MALLOC_CHECK_ ile ilgili bir sorun vardır:
SUID ve SGID'li çalıştırılabilirlerinin istismarı sözkonusu olabilir; bunlar, normal yazılım davranışından ayrılarak standart hata tanımlayıcıya bazı şeyler yazar. Bu nedenle, MALLOC_CHECK_ kullanımı SUID ve SGID'li çalıştırılabilirler için öntanımlı olarak iptal edilmiştir. Ancak sistem yöneticisi tarafından /etc/suid-debug dosyası eklenerek etkinleştirilebilir (bu dosyanın içeriği önemli değildir, dosya boş olabilir).
Öyleyse MALLOC_CHECK_ kullanımı ve -lmcheck seçeneğiyle ilintileme arasında ne fark vardır? -lmcheck geriye uyumluluk adına vardır. Her ikisi de aynı yazılım hataları için kullanılırsa da MALLOC_CHECK_ kullandığınızda yazılımı yeniden derlemek gerekmez.
Bellek Ayırma Kancaları
GNU C kütüphanesi, malloc, realloc ve free işlevlerinin davranışını, işlevle ilgili bir kanca işlev belirterek değiştirebilmenizi sağlar. Örneğin, özdevimli bellek ayırma kullanılan yazılımlarda hata ayıklamaya yardımcı olarak bu kancaları kullanabilirsiniz.
Kanca değişkenler malloc.h başlık dosyasında tanımlanmıştır.
__malloc_hook
değişken
Bu değer, her malloc çağrısında kullanılan işleve bir göstericidir. malloc'a benzeyecek bu işlevi siz tanımlayacaksınız; şöyle:
void *function (size_t boyut, const void *çağıran)
çağıran'ın değeri, malloc çağrıldığında yığıtta bulunan dönüş adresidir. Bu değer yazılımın bellek tüketimini izlemenizi mümkün kılar.
__realloc_hook
değişken
Bu değer, her realloc çağrısında kullanılan işleve bir göstericidir. realloc'a benzeyecek bu işlevi siz tanımlayacaksınız; şöyle:
void *function (void *gösterici, size_t boyut, const void *çağıran)
çağıran'ın değeri, realloc çağrıldığında yığıtta bulunan dönüş adresidir. Bu değer yazılımın bellek tüketimini izlemenizi mümkün kılar.
__free_hook
değişken
Bu değer, her free çağrısında kullanılan işleve bir göstericidir. free'ye benzeyecek bu işlevi siz tanımlayacaksınız; şöyle:
void function (void *gösterici, const void *çağıran)
çağıran'ın değeri, free çağrıldığında yığıtta bulunan dönüş adresidir. Bu değer yazılımın bellek tüketimini izlemenizi mümkün kılar.
__memalign_hook
değişken
Bu değer, her memalign çağrısında kullanılan işleve bir göstericidir. memalign'a benzeyecek bu işlevi siz tanımlayacaksınız; şöyle:
void *function (size_t adımboyu, size_t boyut, const void *çağıran)
çağıran'ın değeri, free çağrıldığında yığıtta bulunan dönüş adresidir. Bu değer yazılımın bellek tüketimini izlemenizi mümkün kılar.
Dikkat
Bu işlevlerden birine bir kanca olarak tanımladığınız işlevin, öncelikle kancayı eski değerine döndürmeden bu işlevi ardışık olarak çağırmadığından emin olmalısınız. Aksi takdirde, yazılımınız sonsuz döngüye takılacaktır. İşlevi ardışık olarak çağırmadan önce tüm kancaları önceki değerlerine döndürdüğünüzden emin olmalısınız. Bir ardışık çağrıdan geri dönüldüğünde, bir kanca kendisini değiştirebileceğinden tüm kancalar yeniden kaydedilmelidir.
__malloc_initialize_hook
değişken
Bu değişkenin değeri, malloc gerçekleştirmesi ilklendirildiğinde bir kere çağrılan bir işleve göstericidir. Bu zayıf bir değişkendir ve aşağıdaki gibi bir tanımlama ile yazılım tarafından değiştirilebilir:
void (*__malloc_initialize_hook) (void) = ilkendirme_kancam;
Bakmak için en iyi zaman, malloc kanca işlevlerinin güvenle kurulduğu zamandır. Kanca işlevler, malloc'la ilgili işlevleri ardışık çağırırsa, malloc'un __malloc_hook'a atandığı sırada kendisini düzgün olarak ilklendirmesi gerekir. Diğer yandan, kanca işlevler kendi malloc gerçeklemelerini sağlarlarsa, kancaların yazılımdaki ilk malloc çağrısı tamamlanmadan önce atanması yaşamsal önemdedir. Çünkü aksi takdirde, örneğin bir normal kancasız malloc'la sağlanan bir blok daha sonra bir __free_hook üzerinden elde edilmelidir.
Her iki durumda da sorun __malloc_initialize_hook tarafından gösterilen bir yazılımcı tanımlı işlev içinden ayarlanması ile çözümlenebilir ve böylece kancalar doğru zamanda güvenle ayarlanmış olur.
Aşağıdaki örnekte __malloc_hook ve __free_hook değişkenlerinin nasıl kullanıldığı gösterilmiştir. malloc veya free her çağrıldığında bir bilgi basan bir işlev kurulmaktadır. Bu örnekte, yazılımda realloc ve memalign işlevlerinin bulunmadığı varsayılmıştır.
/* __malloc_hook ve __free_hook için prototipler */
#include <malloc.h>

/* Kancalarımız için prototipler  */
static void my_init_hook (void);
static void *my_malloc_hook (size_t, const void *);
static void my_free_hook (void*, const void *);

/* C kütüphanesindeli ilklendirme kancasının üstüne yazalım. */
void (*__malloc_initialize_hook) (void) = my_init_hook;

static void my_init_hook (void)
{
  old_malloc_hook = __malloc_hook;
  old_free_hook = __free_hook;
  __malloc_hook = my_malloc_hook;
  __free_hook = my_free_hook;
}

static void * my_malloc_hook (size_t size, const void *caller)
{
  void *result;
  /* tüm eski kancaları önceki değerlerine getirelim */
  __malloc_hook = old_malloc_hook;
  __free_hook = old_free_hook;
  /* Ardışık çağıralım */
  result = malloc (size);
  /* belirlenen kancaları kaydedelim */
  old_malloc_hook = __malloc_hook;
  old_free_hook = __free_hook;
  /* printf, malloc'u  tekrar çağırmamalı. */
  printf ("malloc (%u), %p döndürdü\n", (unsigned int) size, result);
  /* Kendi kancalarımızı önceki değerlerine getirelim */
  __malloc_hook = my_malloc_hook;
  __free_hook = my_free_hook;
  return result;
}

static void
my_free_hook (void *ptr, const void *caller)
{
  /* tüm eski kancaları önceki değerlerine getirelim */
  __malloc_hook = old_malloc_hook;
  __free_hook = old_free_hook;
  /* Ardışık çağıralım */
  free (ptr);
  /* belirlenen kancaları kaydedelim */
  old_malloc_hook = __malloc_hook;
  old_free_hook = __free_hook;
  /* printf, free'yi  tekrar çağırmamalı. */
  printf ("gösterici %p serbest bırakıldı\n", ptr);
  /* Kendi kancalarımızı önceki değerlerine getirelim */
  __malloc_hook = my_malloc_hook;
  __free_hook = my_free_hook;
}

main ()
{
  …
}
mcheck işlevi böyle kancalar kurularak çalışır.
malloc ile Bellek Ayırma İstatistikleri
Özdevimli bellek ayırma hakkında mallinfo işlevini kullanarak bilgi edinebilirsiniz. Bu işlev ve onunla ilişkili veri türü malloc.h başlık dosyasında bildirilmiştir. Standart SVID/XPG sürümünün oluşumlarıdır.
struct mallinfo
veri türü
Bu yapı özdevimli bellek ayırıcı hakkında bilgi döndürmek için kullanılır. Aşağıdaki üyelere sahiptir:
int arena
malloc tarafından sbrk ile ayrılan belleğin bayt cinsinden toplam boyudur.
int ordblks
Kullanılmayan parçaların sayısıdır. (Bellek ayırıcı dahili olarak işletim sistemindeki bellek parçalarını alır ve tek tek malloc çağrılarına dilimleyerek dağıtır. Bkz. malloc için Yeterlik Kaygıları.)
int smblks
Bu alan kullanılmamıştır.
int hblks
mmap ile ayrılan parçaların toplam sayısıdır.
int hblkhd
mmap ile ayrılan belleğin bayt cinsinden toplam boyudur.
int usmblks
Bu alan kullanılmamıştır.
int fsmblks
Bu alan kullanılmamıştır.
int uordblks
malloc tarafından alınmayan parçaların işgal ettiği toplam boyuttur.
int fordblks
Serbest bırakılan (kullanımda olmayan) parçaların işgal ettiği belleğin toplam boyudur.
int keepcost
Normalde yığın belleğin son sınırındaki (sanal adres alanının veri bölütünün yüksek ucu) en tepe dağıtılabilir parçanın boyudur.
struct mallinfo mallinfo
(void)
işlev
Bu işlev o anki özdevimli bellek kullanımı hakkında struct mallinfo yapı türünde bilgi döndürür.
malloc ile İlgili İşlevlerin Özeti
Burada malloc ile çalışan işlevlerin bir özeti bulunmaktadır:
void *malloc
(size_t boyut)
boyut baytlık bir blok ayırır. Bkz. Özdevimli Olarak Basit Bellek Ayırma.
void free
(void *gösterici)
malloc ile ayrılan belleği serbest bırakır. Bkz. malloc ile Ayrılan Belleğin Serbest Bırakılması.
void *realloc
(void  *gösterici,
 size_t yeniboyut)
malloc ile ayrılan belleği büyütür ya da küçültür. Bunu kimi zaman veriyi başka bir yere kopyalayarak yapar. Bkz. Bir Bellek Bloğunun Boyutunun Değiştirilmesi.
void *calloc
(size_t elmsayısı,
 size_t elmboyu)
malloc kullanarak elmsayısı * elmboyu baytlık bir blok ayırır ve içini sıfırlarla doldurarak temizler. Bkz. Temizlenmiş Bellek Ayırma.
void *valloc
(size_t boyut)
Sayfa boyunda adresleme ile boyut uzunlukta blok ayırır. Bkz. Bellek Bloklarının Hizalanarak Ayrılması.
void *memalign
(size_t adımboyu,
 size_t boyut)
adımboyunun katlarında adreslenen boyut baytlık bir blok ayırır. Bkz. Bellek Bloklarının Hizalanarak Ayrılması.
int mallopt
(int param,
 int değer)
Ayarlanabilir parametreleri ayarlar. Bkz. Ayarlanabilir Malloc Parametreleri.
int mcheck
(void (*çıkış_işlevi) (void))
malloc'a özdevimli ayrıan bellek üzerinde arasıra tutarlılık denetimi yapmasını ve bir tutarsızlık bulunursa çıkış_işlevini çağırmasını söyler. Bkz. Yığın Bellek Tutarlılık Denetimi.
void *(*__malloc_hook)
(size_t      boyut,
 const void *çağıran)
Çağrıldığında malloc kullanan bir işleve gösterici.
void *(*__realloc_hook)
(void       *gösterici,
 size_t      boyut,
 const void *çağıran)
Çağrıldığında realloc kullanan bir işleve gösterici.
void (*__free_hook)
(void       *ptr,
 const void *çağıran)
Çağrıldığında free kullanan bir işleve gösterici.
void (*__memalign_hook)
(size_t      boyut,
 size_t      adımboyu,
 const void *çağıran)
Çağrıldığında memalign kullanan bir işleve gösterici.
struct mallinfo mallinfo
(void)
Özdevimli bellek kullanımı hakkında bilgi döndürür. Bkz. malloc ile Bellek Ayırma İstatistikleri.
Önceki Üst Ana Başlık Sonraki
C Yazılımlarında Bellek Ayırma Başlangıç Bellek Ayırmada Hata Ayıklama
Bir Linux Kitaplığı Sayfası