Konuya başlamadan önce maliyet olayına değinelim. Derleme zamanında yer ayırmak çalışma zamanından yer ayırmaktan daha az maliyetlidir. Buda demek oluyor ki gerek olmadığı sürece dinamik ömürlü nesne kullanmak gereksiz ve maliyetli.
Konumuza dönüp hangi standart fonksiyonları inceleyeceğiz bir bakalım. Fonksiyonlarımız;
/* Prototipler*/ (Function Prototype)
Malloc :
void* malloc (size_t size);
Calloc :
void* calloc (size_t num, size_t size);
Realloc :
void* realloc (void* ptr, size_t size);
Free :
void free (void* ptr);
! size_t işaretsiz tamsayı (unsigned int) türüne typedef edilmiştir.
Fonksiyonların protiplerini gördüğümüze göre ne iş yapar nasıl kullanılırlar bir bakalım.
Malloc :
void* malloc (size_t size);
-Malloc fonksiyonu bellekte yer ayırmak için kullanılır. Parametresi ayrılacak bellek boyutudur. Parametre size_t ye typedef edilmiştir size_t sizeof operatörnün geri dönüş değeridir. T türüne göre kullanımı şöledir (T herhangi bir tür belirttiği varsayılırsa)
T *ptr;
ptr = (T *)malloc(sizeof(T)); /*burada fonksiyon T türünün kapladığı yer kadar alanı bellekte ayırmıştır*/
Şimdi kodu incelersek. T * türünden bir değişken tanımladık bu değişken T türünden bir adres turuyor. malloc ile bellekte T türünün kapladığı alan kadar yer ayırdık ve pointerımıza bu bölgeyi tutturduk. Böylece *ptr ile o bölgeye istediğimiz atamayı yapabilmekteyiz.
Anahtar Notlar :
-malloc fonksiyonundan sonra if (ptr == NULL) ile bir kontrol yapmalıyız. malloc eğer bellekte yer ayıramaz ise NULL adres ile geri döner.
- malloc ile ayırılan yer atama yapmadan kullanılmamalıdır. Undefined Behavior bkz. 'a neden olursunuz. malloc ayırıdığı yeri set etmeden geri döner yani çöp değer ile. (calloc set ederek geri döner)
-malloc fonksiyonunun parametresine sizeof girilmesi taşınabilirliği sağlar örneğin int her sistemde 4 bayt olmak zorunda değildir.
-malloc ile ayrılan yer program sonlanmadan free edilmelidir.(free yazının sonunda işlenecektir)
-malloc fonksiyonunun geri dönüş değerini atarken cast etmemek.(ptr = (int *)malloc...)
...
Calloc :
void* calloc (size_t num, size_t size);
-Calloc fonksiyonuda malloc gibi bellekte yer ayırır. Parametrelerinden birincisi kaç adet ayrılacak sorusunun cevabı, ikincisi ise ayrılacak bir adet değişkenin bellekteki kapladığı yerdir(sizeof'u). Geri dönüş değeri ise ayıramazsa NULL adres ayırırsa ayrıdığı yerin adresi(birden fazla ayrılacaksa ilk adres dizi mantığı). Calloc malloc ile aynı işlemi yapmaktadır yani malloc yerine calloc calloc yerine malloc kullanmak birşey değiştirmez fakat calloc ayırdığı bellek gözünü 0 ile set eder. Bunun zorunlu olduğu yerlerde calloc kullanılır yada malloc kullanıldıktan sonra memset ile set edilir.
int türüne göre kullanımına bir örnek;
int x, i; int *ptr; printf("Kac adet tamsayi ayıralım\n"); scanf("%d", &x); ptr = (int *)calloc(x, sizeof(int)); //calloc ile yer ayırdık if (ptr == NULL) // yer ayırma işleminin başarı kontrolü printf("yer ayıramadık"); for (i = 0; i < x; ++i) // dizimizi yazdırdık printf("%d", ptr[i]); /* ekrana bütün elemanları 0 basacaktır*/
Realloc :
void* realloc (void* ptr, size_t size);
-Evet arkadaşlar bellekte yer ayırmayı öğrendik peki programımızda ayırdığımız yeri büyütmemiz, küçültmemiz istenirse ne yapacağız. İşte burada devreye realloc fonksiyonumuz girmektedir. Bu fonksiyon bellekte ayrılan belleği büyültmeye, küçültmeye veya daha doğru olarak yeniden ayırmaya yarar (neden yeniden ayırma dediğimizi anlatacağım). Şimdi parametreleri inceleyelim, birinci parametremiz ayrılmış bellek bloğunun adresini istemektedir, ikinci parametremiz ise yeni belleğin boyutu.
int türüne göre kullanımına bir örnek yaparsak;
int x, y, i; int *ptr; printf("Kac adet tamsayi ayıralım\n"); scanf("%d", &x); ptr = (int *)calloc(x, sizeof(int)); //calloc ile yer ayırdık if (ptr == NULL) // yer ayırma işleminin başarı kontrolü printf("yer ayıramadık"); printf("Kac adet arttıralım"\n"); scanf("%d", &y); ptr = (int *)realloc(ptr, (x + y) * sizeof(int)); // bellekte boyutumuzu y kadar arttırmış olduk if (ptr == NULL) printf("buyutemedik");
Anahtar Notlar :
-realloc bellekte tekrar yer ayırdığında aynı bellek gözünü büyültür diye bir garanti vermemektedir. Eğer başka bir gösterici ile bu bellek bloğunu gösteriyor isek pointer'ı güncellememiz gerek güncellemezsek invalid pointer (kendisi hayatta gösterdiği yer hayatta olmayan pointer) olur. Pointer 'ı dereferens ettiğimizde Undefined Behavior bkz. durumuna düşeriz.
-realloc fonksiyonuna birinci parametreyi NULL adres gönderirsek malloc gibi davranır.
-Aynı yeri büyütmek zorunda değildir kopyalar ve eski yeri free eder.
-realloc büyütemezse NULL adres ile geri döner
-ikinci parametreyi 0 girersek free görevi yapar. (Sanırım bu durum son standartlarla güncellendi araştırıp yazıyı güncelleyeceğim).
...
Free :
void free (void* ptr);
-Artık bellekte yerlerimizi ayırtmayı büyütmeyi küçültmeyi öğrendik artık bu yerleri serbest bırakmayı öğrenme vaktimiz geldi. Free fonksiyonu ismi gibi parametre olarak gönderilen bellek gözünü serbest bırakır. Eğer bırakmazsak ne olur derseniz bellek sızıntısı (memory leak) meydana gelir. Çünkü program serbest bırakmadığı bir yeri tekrar kullanamaz. Bu nedenle free etmek (serbest bırakmak) zorunludur. Protoripi incelersek geridönüş değeri void yani yoktur, parametresi ise free edilecek bellek gözüdür. Kullanımı şu şekildedir.
T *ptr;
ptr = (T *)malloc(sizeof(T)); //burada fonksiyon T türünün kapladığı yer kadar alanı bellekte ayırmıştır
if (ptr == NULL)
printf("yer ayıramadık");
free(ptr); //bellek gözünü serbest bıraktık
Anahtar Notlar :
-free ettikten sonra ptr 'ye erişmemek gerekir.
-Dinamik olmayan bellek bloğu free edilmemelidir.
-İki kere free edilmemelidir.
-Parametre olarak NULL adres girmenin bir zararı yararı yoktur.
...
Yazımızın sonuna gelmiş bulunmaktayız umarım faydalı olabilmişimdir. Belirtmeyi unuttuğum yerler az da olsa olabilir tekrar okuyup güncellemeleri yapacağım. Hepinize teşekkürler hatam oldu ise affola.
Hiç yorum yok:
Yorum Gönder