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.
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.
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.
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.
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.
|
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.