SlideShare a Scribd company logo
1 of 5
Dinamik BellekYönetimi – Dynamic Memory Management
*** Yazının başından sonuna kadar bazı noktalarda fonksiyon(function) kelimesi yerine türkçe karşılığı
işlev kelimesi kullanılmıştır. ***
Bu yazımız da C dilinde dinamik bellek yönetimi konusunu işleyeceğiz. Dinamik bellek yönetimi C
dilinde çok önemli bir yer tutmaktadır. Hiç kuşkusuz bunun sebeplerinden birisi maliyet durumudur.
Yani sınırsız bir bellek alanımızın olmayışı bizi belleğimizi verimli kullanmaya itiyor. Aksi halde
yazılan programlar gerektiğinden fazla bellek tüketecek ve yavaş çalışacaktır.
Bellek yönetimine girmeden bellek yapısından, heap ve stack kavramlarından bahsetmek gerekir.
Stack ile başlayalım.
Stack, türkçe karşılığı yığın olan RAM bellekte bulunan soyut bir yapıdır. Belirli bir düzene ve
kurala göre verileri içerisinde saklar. Bu kural yapısı kısaca LIFO yani (Last in First Out) son giren
ilk çıkar mantığında çalışmaktadır.
Kısaca LIFO nun mantığını günlük hayattan örneklendirmek gerekirse şöyle açıklayabilirim.
Mutfakta kirli tabaklarınız var önce deterjanla köpürtüp temizleyip üst üste diziyorsunuz. Bu
şekilde 10-15 tabağı üst üste dizdiğinizi düşünün. Temizleme işleminin ardından durulama aşaması
geldiğinde ilk olarak, en alttaki tabaktan değil en üstteki tabaktan başlarsınız. İlk önce en üstte ki
tabağı alır durular bir kenara koyarsınız sonra sırasıyla diğerlerini yıkar durularsınız. LIFO
mantığıda bu şekildedir. Stack de veriler, son giren Ilk çıkar mantığı ile işleme tabi tutulurlar. Bir
düzen vardır. Biz bu yapıyı farkında olmadan günlük hayatta bir çok kez kullanıyoruz. Bizim
yerimize kullandığımız bilgisayar bunu otomatik olarak yapıyor.
İlk değer vermediğimiz bir pointer oluşturduğumuz da bu pointer bellekte stack alanında bulunur.
Örnek char * türünde bir pointer oluşturalım.
Char *ptr;
Heap ile devam edelim.
Heap yapısının en önemli özelliği, veriler stack de olduğu gibi bir düzen veya kurala(LIFO) göre
değil karışık bir şekilde tutulurlar. Bir diğer fark ise Stack üzerinde ki veri hemen silinebilirken
Heap de ki veriyi silmek için çöp toplayıcı (garbage collector) algoritması gerekir.
Dinamik bellek yönetiminde bellek üzerinden belirli bir boyutta bellek alanı ayırmak istediğimizde,
bu alan heap den alınır. Aynı şekilde bu alanı büyütmek veya küçültmek istediğimiz de, gene heap
üzerinde işlem yapılır.
Yukarıda oluşturduğumuz pointer’a bir dizinin adresi ile ilk değer verelim.
char a[20] = { 0 };
char *ptr = a;
Artık ptr, a dizisinin adresini tutuyor.
Neden adres operatörünü kullanmadığımızı merak ediyor olabilirsiniz. Dizi işlemlerinde derleyiciye
char *ptr = &a; demek ile char *ptr = a; demek arasında bir fark yoktur.
Derleyiciden derleyiciye fark olsa da, tanımladığınız pointer veya değişken türlerinin bellekte
kaplayacağı alan az çok bellidir. Yukarıda tanımadığımız pointer bellek üzerinde 8 byte yer
kaplamaktadır. Linux altında kullandığım GCC derleyicisinde, tanımlanan değişken veya
pointerlara ait tür bilgileri ve hafızada kapladıkları alanları şöyledir.
Int türü 4 byte
Int * türü 8 byte
Double türü 8 byte
Double * türü 8 byte
Char türü 1 byte
Char * türü 8 byte
Bu bilgileri elde etmek için sizeof() işlevi kullanılabilir.
#include <stdio.h>
int main(){
printf("sizeof(char *) = %dn", sizeof(char *));
printf("sizeof(int *) = %dn", sizeof(int *));
printf("sizeof(int) = %dn", sizeof(int));
printf("sizeof(char) = %dn", sizeof(char));
printf("sizeof(double) = %dn", sizeof(double));
printf("sizeof(double *) = %dn", sizeof(double *));
return 0;
}
Şimdi gelelim dinamik bellek yönetimi fonksiyonlarını tanımaya.
Standart olarak C de gelen dinamik bellek yönetimi ile ilgili fonksiyonların bildirimleri “stdlib.h”
başlık dosyası içerisinde yer alır. Bu fonksiyonlar şunlardır:
malloc();
calloc();
realloc();
free();
Tanımladığımız diziler genelde belli boyutlara sahip oldukları için bellek üzerinde kapladıkları alanı
tahmin etmek kolaydır. Fakat öyle senaryolar var ki, tanımladığımız dizilerin boyutunu kestirmek
zor oluyor. Bu gibi durumlar da dizilerin boyutu dinamik olarak küçülüp büyüyebiliyor. Örnek,
yemekhaneye giriş çıkışların kontrol edildiği bir yazılımınız var. Yemekhaneye giriş çıkış yapan
kişilerin isim, soyisim, yaş, departman ve giriş saati gibi bilgilerini diziler üzerinde tutuyorsunuz.
Fakat o gün yemekhaneye kaç kişinin giriş yapacağını kestiremiyorsunuz. Giriş yapanların sayısı 10
da olabilir 100 de.. Siz de bu duruma uygun bir biçimde dizi tanımlamalısınız. Bu duruma uygun bir
biçimde dizi tanımlamak biraz zor ama dinamik bellek yönetimi ile kolay..
Şimdi fonksiyonlarımızın bildirimlerini ve tek tek nasıl kullanıldıklarını görelim.
Malloc işlevi
void *malloc(size_t size);
Gördüğünüz gibi malloc işlevi adres döndüren bir işlev.. Bizden size_t türünden bir boyut bilgisi
istiyor. (size_t türü unsigned int’tir)
Bize ne kadar bellek alanı istediğimizi soruyor ve bize bu bellek alanını kullanabilmemiz için bir
adres bilgisi dönüyor. Adres bilgisini saklamak için pointerları kullanıyoruz.
Şimdi bellekten 40 byte’lık bir alan tahsis edelim.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr = malloc(sizeof(int) * 10);
if(ptr){
printf(“Alan tahsis edildi”);
}
else{
printf(“Yetersiz bellek.n”);
}
return 0;
}
Calloc işlevi
Malloc işlevi ile 40 bytelık bir alan tahsisi gerçekleştirdik. Fakat bilmemiz gereken bir konu daha
var. Malloc işlevi ile tahsis edilen bellekte ki alanlar çöp değerler ile tahsis edilir.
Calloc işlevi ise tıpkı malloc işlevi gibi alan tahsis eder ve malloc işlevinden farklı olarak tahsis
ettiği bellek alanını sıfırlar. Yani bellek adreslerinden veri okunduğunda değer olarak 0 bulunur.
Calloc işlevinin bildirimi (function declaration) şu şekilde:
void *calloc(size_t ntane, size_t nboyutunda);
Calloc işlevinin parametre olarak bizden istediği iki adet argüman var. Bunlardan ilki kaç byte alan
istenildiğini belirten argüman, bir diğeri ise hangi tür boyutta istenildiğini belirten argüman..
Aşağıdaki kod bloğu daha açıklayıcı olur sanırım.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *cptr = calloc(10, sizeof(int)); // sizeof (int) değer olarak 4 byte döner.. 4 * 10 = 40 byte
for(int i=0; i<10; ++i){
printf(“cptr[%d] = %dn”, i, cptr[i]);
}
return 0;
}
Hatırlarsak, malloc işlevinden farklı olarak calloc işlevi bellekteki değerleri sıfırlıyordu. Derleyip
çalıştırdığımız da bize ayrılan bellek alanında ki değerleri görebiliriz.
Realloc işlevi
Yazının ilk başında verdiğim yemekhane örneğine bir gönderme ile başlayalım. Hatırlarsak
yemekhane yazılımımız da bir dizi ile yemekhaneye giriş çıkış yapan kişilerin bilgilerini
tutuyorduk. Fakat kaç kişinin giriş yapacağı konusunda bir fikrimiz olmadığından, dizi ile
ayırdığımız bellek bloğu bize yetersiz gelebilir. Bu durumda ayırdığımız bellek bloğunu büyütüp
küçültme ihtiyacı duyarız. Bu işi yapan işlev realloc işlevidir.
Realloc işlevinin bildirimi şu şekildedir:
void *realloc(void *vp; size_t new_size);
Realloc işlevinin bildiriminden anlayacağımız üzere, işlev bizden iki argüman istemektedir. Birinci
argüman büyültme veya küçültme yapacağımız bellek bloğunun adresi, ikinci argüman ise adresi
alınan bellek bloğunun yeni boyutu.. İşlevi şu şekilde kullanıyoruz:
#include <stdio.h>
#include <stdlib.h>
int main()
{
size_t n;
printf("kac tamsayi: ");
scanf("%zu", &n);
int *pd = (int *)malloc(n * sizeof(int));
if (!pd) {
printf("bellek yetersizn");
}
size_t nplus;
printf("kac tamsayi daha ilave edilsin: ");
scanf("%zu", &nplus);
pd = realloc(pd, (n + nplus) * sizeof(int));
if (!pd) {
printf("bellek yetersizn");
return 1;
}
}
Kodu yorumlamaya başlarsak :
size_t türünde n adında bir değişken tanımlıyoruz. Scanf ile tanımladığımız değişkene bir tamsayi
değeri atıyoruz. Daha sonra pd adında, geri dönüş türü int * olan bir pointer tanımlıyoruz ve buna
değer olarak int * türüne cast edilmiş(dönüştürülmüş) malloc işlevi ile n * sizeof(int) kadar bellek
alanı tahsis ediyoruz. İf deyimi ile bellek alanının tahsisi başarılı mı değil mi kontrol ediyoruz.
Artık pd adında bir pointer da n adet, int türünden bellek alanımız var. Bu bellek alanını büyütmek
için tekrar size_t türünden nplus adında bir değişken tanımlıyoruz. Printf işlevi ile var olan bellek
alanına ne kadar daha ekleme yapılması istenildiğini soruyor ve bu değeri scanf işlevi ile nplus
değişkenine değer olarak veriyoruz.
Daha sonra realloc işlevini çağırıp işlem yapılacak bellek adresinin tutulduğu pointer’ı veriyoruz.
İkinci argüman olarak da var olan n sayısına nplus ı ekleyip sizeof(int) geri dönüş değeri ile
çarpıyoruz. Sizeof(int) geri dönüş değerini 4 byte döneceğinden n + nplus toplamı 4 ile çarpılacak
ve çıkan değer kadar “byte” bellekten tahsis edilmiş olacak. Bu örnek bellek alanının
büyütülmesine verilen örnektir.
Free işlevi
free işlevi, malloc veya calloc ile tahsis ettiğimiz bellek alanlarını işimiz bittiğinde tekrar serbest
bırakmamıza yarayan çok güzel bir işlevdir. Dinamik bellek yönetiminde malloc veya calloc ile
ayrılan bellek, heap bellek alanından verilir demiştik. Heap alanından aldığımız bellek bloğunu free
ile geri vermezsek bellek alanı dolduğunda ve program işini yapamayacak duruma geldiğinde
“memory leak” dediğimiz bellek sızıntısına sebep olur.
***Aşağıda madde madde belirtilen davranışlarda kesinlikle bulunmayın!***
1-) Dinamik bellek işleviyle yeri elde edilmemiş bir bellek bloğunu asla free etme girişiminde
bulunmayın.
2-) free işleviyle bir dinamik bellek bloğunu küçültme girişiminde bulunmayın. Free ile bloğun
tamamını geri verebilirsiniz.
3-) free edilmiş bir bellek bloğunun adresini tekrar free işlevine döndürmek tanımsız davranıştır.
(undefined behavior)
4-) Geri verilmiş bir bellek bloğunu kullanma girişiminde bulunmayın. Tanımsız
davranıştır.(undefined behavior)
5-) Tahsis ettiğiniz dinamik bellek bloğunu free ile geri vermeyi unutmayın.
Free işlevinin bildirimi şöyledir.
Void free(void *ptr);
Gördüğünüz üzere free bizden yanlızca free edilecek yani geri verilecek bellek bloğunun adresini
istiyor. Yukarıda malloc ve calloc işlevleri ile tahsis ettiğimiz bellek bloklarını şu şekilde geri
verebiliriz.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *cptr = calloc(10, sizeof(int)); // sizeof (int) değer olarak 4 byte döner.. 4 * 10 = 40 byte
for(int i=0; i<10; ++i){
printf(“cptr[%d] = %dn”, i, cptr[i]);
}
free(cptr); // geri verilecek bellek bloğunun adresi
return 0;
}
Yazımızı okuma zahmetinde bulunduğunuz için teşekkürler.

More Related Content

What's hot

Kablosuz Ağlar ve Güvenlik Riskleri
Kablosuz Ağlar ve Güvenlik RiskleriKablosuz Ağlar ve Güvenlik Riskleri
Kablosuz Ağlar ve Güvenlik Riskleri
BGA Cyber Security
 
SynFlood DDOS Saldırıları ve Korunma Yolları
SynFlood DDOS Saldırıları ve Korunma YollarıSynFlood DDOS Saldırıları ve Korunma Yolları
SynFlood DDOS Saldırıları ve Korunma Yolları
BGA Cyber Security
 
Firewall presentation m. emin özgünsür
Firewall presentation   m. emin özgünsürFirewall presentation   m. emin özgünsür
Firewall presentation m. emin özgünsür
emin_oz
 
Online voting system
Online voting systemOnline voting system
Online voting system
Arti Gupta
 

What's hot (20)

Security Testing with OWASP ZAP in CI/CD - Simon Bennetts - Codemotion Amster...
Security Testing with OWASP ZAP in CI/CD - Simon Bennetts - Codemotion Amster...Security Testing with OWASP ZAP in CI/CD - Simon Bennetts - Codemotion Amster...
Security Testing with OWASP ZAP in CI/CD - Simon Bennetts - Codemotion Amster...
 
EXPLOIT POST EXPLOITATION
EXPLOIT POST EXPLOITATIONEXPLOIT POST EXPLOITATION
EXPLOIT POST EXPLOITATION
 
Network Security Fundamental
Network Security FundamentalNetwork Security Fundamental
Network Security Fundamental
 
Caldera İle Saldırı Simülasyonu
Caldera İle Saldırı SimülasyonuCaldera İle Saldırı Simülasyonu
Caldera İle Saldırı Simülasyonu
 
Hacking SIP Like a Boss!
Hacking SIP Like a Boss!Hacking SIP Like a Boss!
Hacking SIP Like a Boss!
 
LLMNR ve NetBIOS Poisoning
LLMNR ve NetBIOS PoisoningLLMNR ve NetBIOS Poisoning
LLMNR ve NetBIOS Poisoning
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
 
Güvenli Veri Silme ve Dosya Kurtarma
Güvenli Veri Silme ve Dosya KurtarmaGüvenli Veri Silme ve Dosya Kurtarma
Güvenli Veri Silme ve Dosya Kurtarma
 
Kablosuz Ağlar ve Güvenlik Riskleri
Kablosuz Ağlar ve Güvenlik RiskleriKablosuz Ağlar ve Güvenlik Riskleri
Kablosuz Ağlar ve Güvenlik Riskleri
 
Linux Kullanım Rehberi
Linux Kullanım RehberiLinux Kullanım Rehberi
Linux Kullanım Rehberi
 
Kablosuz Ağlara Yapılan Saldırılar
Kablosuz Ağlara Yapılan SaldırılarKablosuz Ağlara Yapılan Saldırılar
Kablosuz Ağlara Yapılan Saldırılar
 
Sızma Testlerinde Parola Kırma Saldırıları
Sızma Testlerinde Parola Kırma SaldırılarıSızma Testlerinde Parola Kırma Saldırıları
Sızma Testlerinde Parola Kırma Saldırıları
 
Bir Ransomware Saldırısının Anatomisi. A'dan Z'ye Ransomware Saldırıları
Bir Ransomware Saldırısının Anatomisi. A'dan Z'ye Ransomware SaldırılarıBir Ransomware Saldırısının Anatomisi. A'dan Z'ye Ransomware Saldırıları
Bir Ransomware Saldırısının Anatomisi. A'dan Z'ye Ransomware Saldırıları
 
Nmap101 Eğitim Sunumu - Nmap Kullanım Kılavuzu
Nmap101 Eğitim Sunumu - Nmap Kullanım KılavuzuNmap101 Eğitim Sunumu - Nmap Kullanım Kılavuzu
Nmap101 Eğitim Sunumu - Nmap Kullanım Kılavuzu
 
SynFlood DDOS Saldırıları ve Korunma Yolları
SynFlood DDOS Saldırıları ve Korunma YollarıSynFlood DDOS Saldırıları ve Korunma Yolları
SynFlood DDOS Saldırıları ve Korunma Yolları
 
Firewalls
FirewallsFirewalls
Firewalls
 
Firewall presentation m. emin özgünsür
Firewall presentation   m. emin özgünsürFirewall presentation   m. emin özgünsür
Firewall presentation m. emin özgünsür
 
Metasploit El Kitabı
Metasploit El KitabıMetasploit El Kitabı
Metasploit El Kitabı
 
INTERNET VE YEREL AĞ SIZMA TESTLERİ
INTERNET VE YEREL AĞ SIZMA TESTLERİ INTERNET VE YEREL AĞ SIZMA TESTLERİ
INTERNET VE YEREL AĞ SIZMA TESTLERİ
 
Online voting system
Online voting systemOnline voting system
Online voting system
 

Similar to C dilinde dinamik bellek yönetimi (6)

Heap Overflow Zafiyetleri & Exploiting
Heap Overflow Zafiyetleri & ExploitingHeap Overflow Zafiyetleri & Exploiting
Heap Overflow Zafiyetleri & Exploiting
 
Ileri seviye javascript by Azer Koculu
Ileri seviye javascript by Azer KoculuIleri seviye javascript by Azer Koculu
Ileri seviye javascript by Azer Koculu
 
Pivot Unpivot
Pivot UnpivotPivot Unpivot
Pivot Unpivot
 
Templates
Templates Templates
Templates
 
1. Pythonda Sayılar.pdf
1. Pythonda Sayılar.pdf1. Pythonda Sayılar.pdf
1. Pythonda Sayılar.pdf
 
Matlab
MatlabMatlab
Matlab
 

More from MehmetKelepce (6)

XMPP ile OTR Kullanımı
XMPP ile OTR KullanımıXMPP ile OTR Kullanımı
XMPP ile OTR Kullanımı
 
Group Policy Logon Script ile Paylaşım Klasörü Maplemek
Group Policy Logon Script ile Paylaşım Klasörü MaplemekGroup Policy Logon Script ile Paylaşım Klasörü Maplemek
Group Policy Logon Script ile Paylaşım Klasörü Maplemek
 
Web Güvenlik Açıkları - Web Application Vulnerabilities
Web Güvenlik Açıkları - Web Application VulnerabilitiesWeb Güvenlik Açıkları - Web Application Vulnerabilities
Web Güvenlik Açıkları - Web Application Vulnerabilities
 
Zone Transfer Attack
Zone Transfer AttackZone Transfer Attack
Zone Transfer Attack
 
Hedef Odaklı Subdomain Tespiti
Hedef Odaklı Subdomain TespitiHedef Odaklı Subdomain Tespiti
Hedef Odaklı Subdomain Tespiti
 
C dilindeki strtok, remove, rename ve system fonksiyonları.
C dilindeki strtok, remove, rename ve system fonksiyonları. C dilindeki strtok, remove, rename ve system fonksiyonları.
C dilindeki strtok, remove, rename ve system fonksiyonları.
 

C dilinde dinamik bellek yönetimi

  • 1. Dinamik BellekYönetimi – Dynamic Memory Management *** Yazının başından sonuna kadar bazı noktalarda fonksiyon(function) kelimesi yerine türkçe karşılığı işlev kelimesi kullanılmıştır. *** Bu yazımız da C dilinde dinamik bellek yönetimi konusunu işleyeceğiz. Dinamik bellek yönetimi C dilinde çok önemli bir yer tutmaktadır. Hiç kuşkusuz bunun sebeplerinden birisi maliyet durumudur. Yani sınırsız bir bellek alanımızın olmayışı bizi belleğimizi verimli kullanmaya itiyor. Aksi halde yazılan programlar gerektiğinden fazla bellek tüketecek ve yavaş çalışacaktır. Bellek yönetimine girmeden bellek yapısından, heap ve stack kavramlarından bahsetmek gerekir. Stack ile başlayalım. Stack, türkçe karşılığı yığın olan RAM bellekte bulunan soyut bir yapıdır. Belirli bir düzene ve kurala göre verileri içerisinde saklar. Bu kural yapısı kısaca LIFO yani (Last in First Out) son giren ilk çıkar mantığında çalışmaktadır. Kısaca LIFO nun mantığını günlük hayattan örneklendirmek gerekirse şöyle açıklayabilirim. Mutfakta kirli tabaklarınız var önce deterjanla köpürtüp temizleyip üst üste diziyorsunuz. Bu şekilde 10-15 tabağı üst üste dizdiğinizi düşünün. Temizleme işleminin ardından durulama aşaması geldiğinde ilk olarak, en alttaki tabaktan değil en üstteki tabaktan başlarsınız. İlk önce en üstte ki tabağı alır durular bir kenara koyarsınız sonra sırasıyla diğerlerini yıkar durularsınız. LIFO mantığıda bu şekildedir. Stack de veriler, son giren Ilk çıkar mantığı ile işleme tabi tutulurlar. Bir düzen vardır. Biz bu yapıyı farkında olmadan günlük hayatta bir çok kez kullanıyoruz. Bizim yerimize kullandığımız bilgisayar bunu otomatik olarak yapıyor. İlk değer vermediğimiz bir pointer oluşturduğumuz da bu pointer bellekte stack alanında bulunur. Örnek char * türünde bir pointer oluşturalım. Char *ptr; Heap ile devam edelim. Heap yapısının en önemli özelliği, veriler stack de olduğu gibi bir düzen veya kurala(LIFO) göre değil karışık bir şekilde tutulurlar. Bir diğer fark ise Stack üzerinde ki veri hemen silinebilirken Heap de ki veriyi silmek için çöp toplayıcı (garbage collector) algoritması gerekir. Dinamik bellek yönetiminde bellek üzerinden belirli bir boyutta bellek alanı ayırmak istediğimizde, bu alan heap den alınır. Aynı şekilde bu alanı büyütmek veya küçültmek istediğimiz de, gene heap üzerinde işlem yapılır. Yukarıda oluşturduğumuz pointer’a bir dizinin adresi ile ilk değer verelim. char a[20] = { 0 }; char *ptr = a; Artık ptr, a dizisinin adresini tutuyor. Neden adres operatörünü kullanmadığımızı merak ediyor olabilirsiniz. Dizi işlemlerinde derleyiciye char *ptr = &a; demek ile char *ptr = a; demek arasında bir fark yoktur. Derleyiciden derleyiciye fark olsa da, tanımladığınız pointer veya değişken türlerinin bellekte kaplayacağı alan az çok bellidir. Yukarıda tanımadığımız pointer bellek üzerinde 8 byte yer kaplamaktadır. Linux altında kullandığım GCC derleyicisinde, tanımlanan değişken veya pointerlara ait tür bilgileri ve hafızada kapladıkları alanları şöyledir.
  • 2. Int türü 4 byte Int * türü 8 byte Double türü 8 byte Double * türü 8 byte Char türü 1 byte Char * türü 8 byte Bu bilgileri elde etmek için sizeof() işlevi kullanılabilir. #include <stdio.h> int main(){ printf("sizeof(char *) = %dn", sizeof(char *)); printf("sizeof(int *) = %dn", sizeof(int *)); printf("sizeof(int) = %dn", sizeof(int)); printf("sizeof(char) = %dn", sizeof(char)); printf("sizeof(double) = %dn", sizeof(double)); printf("sizeof(double *) = %dn", sizeof(double *)); return 0; } Şimdi gelelim dinamik bellek yönetimi fonksiyonlarını tanımaya. Standart olarak C de gelen dinamik bellek yönetimi ile ilgili fonksiyonların bildirimleri “stdlib.h” başlık dosyası içerisinde yer alır. Bu fonksiyonlar şunlardır: malloc(); calloc(); realloc(); free(); Tanımladığımız diziler genelde belli boyutlara sahip oldukları için bellek üzerinde kapladıkları alanı tahmin etmek kolaydır. Fakat öyle senaryolar var ki, tanımladığımız dizilerin boyutunu kestirmek zor oluyor. Bu gibi durumlar da dizilerin boyutu dinamik olarak küçülüp büyüyebiliyor. Örnek, yemekhaneye giriş çıkışların kontrol edildiği bir yazılımınız var. Yemekhaneye giriş çıkış yapan kişilerin isim, soyisim, yaş, departman ve giriş saati gibi bilgilerini diziler üzerinde tutuyorsunuz. Fakat o gün yemekhaneye kaç kişinin giriş yapacağını kestiremiyorsunuz. Giriş yapanların sayısı 10 da olabilir 100 de.. Siz de bu duruma uygun bir biçimde dizi tanımlamalısınız. Bu duruma uygun bir biçimde dizi tanımlamak biraz zor ama dinamik bellek yönetimi ile kolay.. Şimdi fonksiyonlarımızın bildirimlerini ve tek tek nasıl kullanıldıklarını görelim. Malloc işlevi void *malloc(size_t size); Gördüğünüz gibi malloc işlevi adres döndüren bir işlev.. Bizden size_t türünden bir boyut bilgisi istiyor. (size_t türü unsigned int’tir) Bize ne kadar bellek alanı istediğimizi soruyor ve bize bu bellek alanını kullanabilmemiz için bir adres bilgisi dönüyor. Adres bilgisini saklamak için pointerları kullanıyoruz.
  • 3. Şimdi bellekten 40 byte’lık bir alan tahsis edelim. #include <stdio.h> #include <stdlib.h> int main() { int *ptr = malloc(sizeof(int) * 10); if(ptr){ printf(“Alan tahsis edildi”); } else{ printf(“Yetersiz bellek.n”); } return 0; } Calloc işlevi Malloc işlevi ile 40 bytelık bir alan tahsisi gerçekleştirdik. Fakat bilmemiz gereken bir konu daha var. Malloc işlevi ile tahsis edilen bellekte ki alanlar çöp değerler ile tahsis edilir. Calloc işlevi ise tıpkı malloc işlevi gibi alan tahsis eder ve malloc işlevinden farklı olarak tahsis ettiği bellek alanını sıfırlar. Yani bellek adreslerinden veri okunduğunda değer olarak 0 bulunur. Calloc işlevinin bildirimi (function declaration) şu şekilde: void *calloc(size_t ntane, size_t nboyutunda); Calloc işlevinin parametre olarak bizden istediği iki adet argüman var. Bunlardan ilki kaç byte alan istenildiğini belirten argüman, bir diğeri ise hangi tür boyutta istenildiğini belirten argüman.. Aşağıdaki kod bloğu daha açıklayıcı olur sanırım. #include <stdio.h> #include <stdlib.h> int main() { int *cptr = calloc(10, sizeof(int)); // sizeof (int) değer olarak 4 byte döner.. 4 * 10 = 40 byte for(int i=0; i<10; ++i){ printf(“cptr[%d] = %dn”, i, cptr[i]); } return 0; } Hatırlarsak, malloc işlevinden farklı olarak calloc işlevi bellekteki değerleri sıfırlıyordu. Derleyip çalıştırdığımız da bize ayrılan bellek alanında ki değerleri görebiliriz.
  • 4. Realloc işlevi Yazının ilk başında verdiğim yemekhane örneğine bir gönderme ile başlayalım. Hatırlarsak yemekhane yazılımımız da bir dizi ile yemekhaneye giriş çıkış yapan kişilerin bilgilerini tutuyorduk. Fakat kaç kişinin giriş yapacağı konusunda bir fikrimiz olmadığından, dizi ile ayırdığımız bellek bloğu bize yetersiz gelebilir. Bu durumda ayırdığımız bellek bloğunu büyütüp küçültme ihtiyacı duyarız. Bu işi yapan işlev realloc işlevidir. Realloc işlevinin bildirimi şu şekildedir: void *realloc(void *vp; size_t new_size); Realloc işlevinin bildiriminden anlayacağımız üzere, işlev bizden iki argüman istemektedir. Birinci argüman büyültme veya küçültme yapacağımız bellek bloğunun adresi, ikinci argüman ise adresi alınan bellek bloğunun yeni boyutu.. İşlevi şu şekilde kullanıyoruz: #include <stdio.h> #include <stdlib.h> int main() { size_t n; printf("kac tamsayi: "); scanf("%zu", &n); int *pd = (int *)malloc(n * sizeof(int)); if (!pd) { printf("bellek yetersizn"); } size_t nplus; printf("kac tamsayi daha ilave edilsin: "); scanf("%zu", &nplus); pd = realloc(pd, (n + nplus) * sizeof(int)); if (!pd) { printf("bellek yetersizn"); return 1; } } Kodu yorumlamaya başlarsak : size_t türünde n adında bir değişken tanımlıyoruz. Scanf ile tanımladığımız değişkene bir tamsayi değeri atıyoruz. Daha sonra pd adında, geri dönüş türü int * olan bir pointer tanımlıyoruz ve buna değer olarak int * türüne cast edilmiş(dönüştürülmüş) malloc işlevi ile n * sizeof(int) kadar bellek alanı tahsis ediyoruz. İf deyimi ile bellek alanının tahsisi başarılı mı değil mi kontrol ediyoruz. Artık pd adında bir pointer da n adet, int türünden bellek alanımız var. Bu bellek alanını büyütmek için tekrar size_t türünden nplus adında bir değişken tanımlıyoruz. Printf işlevi ile var olan bellek alanına ne kadar daha ekleme yapılması istenildiğini soruyor ve bu değeri scanf işlevi ile nplus değişkenine değer olarak veriyoruz.
  • 5. Daha sonra realloc işlevini çağırıp işlem yapılacak bellek adresinin tutulduğu pointer’ı veriyoruz. İkinci argüman olarak da var olan n sayısına nplus ı ekleyip sizeof(int) geri dönüş değeri ile çarpıyoruz. Sizeof(int) geri dönüş değerini 4 byte döneceğinden n + nplus toplamı 4 ile çarpılacak ve çıkan değer kadar “byte” bellekten tahsis edilmiş olacak. Bu örnek bellek alanının büyütülmesine verilen örnektir. Free işlevi free işlevi, malloc veya calloc ile tahsis ettiğimiz bellek alanlarını işimiz bittiğinde tekrar serbest bırakmamıza yarayan çok güzel bir işlevdir. Dinamik bellek yönetiminde malloc veya calloc ile ayrılan bellek, heap bellek alanından verilir demiştik. Heap alanından aldığımız bellek bloğunu free ile geri vermezsek bellek alanı dolduğunda ve program işini yapamayacak duruma geldiğinde “memory leak” dediğimiz bellek sızıntısına sebep olur. ***Aşağıda madde madde belirtilen davranışlarda kesinlikle bulunmayın!*** 1-) Dinamik bellek işleviyle yeri elde edilmemiş bir bellek bloğunu asla free etme girişiminde bulunmayın. 2-) free işleviyle bir dinamik bellek bloğunu küçültme girişiminde bulunmayın. Free ile bloğun tamamını geri verebilirsiniz. 3-) free edilmiş bir bellek bloğunun adresini tekrar free işlevine döndürmek tanımsız davranıştır. (undefined behavior) 4-) Geri verilmiş bir bellek bloğunu kullanma girişiminde bulunmayın. Tanımsız davranıştır.(undefined behavior) 5-) Tahsis ettiğiniz dinamik bellek bloğunu free ile geri vermeyi unutmayın. Free işlevinin bildirimi şöyledir. Void free(void *ptr); Gördüğünüz üzere free bizden yanlızca free edilecek yani geri verilecek bellek bloğunun adresini istiyor. Yukarıda malloc ve calloc işlevleri ile tahsis ettiğimiz bellek bloklarını şu şekilde geri verebiliriz. #include <stdio.h> #include <stdlib.h> int main() { int *cptr = calloc(10, sizeof(int)); // sizeof (int) değer olarak 4 byte döner.. 4 * 10 = 40 byte for(int i=0; i<10; ++i){ printf(“cptr[%d] = %dn”, i, cptr[i]); } free(cptr); // geri verilecek bellek bloğunun adresi return 0; } Yazımızı okuma zahmetinde bulunduğunuz için teşekkürler.