SlideShare a Scribd company logo
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

7 leviers pour générer du trafic en Point de Vente
7 leviers pour générer du trafic en Point de Vente7 leviers pour générer du trafic en Point de Vente
7 leviers pour générer du trafic en Point de Vente
Dagobert
 
Communication et le luxe
Communication et le luxeCommunication et le luxe
Communication et le luxe
PMB Com SA
 
Etude identité visuelle France Culture Papiers
Etude identité visuelle France Culture PapiersEtude identité visuelle France Culture Papiers
Etude identité visuelle France Culture Papiers
ADELINE LABOUYSSE
 
Heuristic search-best-first-search
Heuristic search-best-first-searchHeuristic search-best-first-search
Heuristic search-best-first-searchAMIK AL MA'SOEM
 
Linux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflowLinux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflow
Angel Boy
 
21 citations inspirantes sur l'Inbound Marketing
21 citations inspirantes sur l'Inbound Marketing21 citations inspirantes sur l'Inbound Marketing
21 citations inspirantes sur l'Inbound Marketing
Powertrafic
 
Linux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend ProgramingLinux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend Programing
Angel Boy
 
Penggunaan loop sebagai kerangka dasar algoritma
Penggunaan loop sebagai kerangka dasar algoritma Penggunaan loop sebagai kerangka dasar algoritma
Penggunaan loop sebagai kerangka dasar algoritma
Fazar Ikhwan Guntara
 
Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)
Angel Boy
 
L'écosystème du PO à travers le corps humain par Denis St-Michel
L'écosystème du PO à travers le corps humain par Denis St-MichelL'écosystème du PO à travers le corps humain par Denis St-Michel
L'écosystème du PO à travers le corps humain par Denis St-Michel
Agile Montréal
 
mencari nilai minimum menggunakan fungsi rekursif di C
mencari nilai minimum menggunakan fungsi rekursif di Cmencari nilai minimum menggunakan fungsi rekursif di C
mencari nilai minimum menggunakan fungsi rekursif di C
kir yy
 
Positionnement
PositionnementPositionnement
Positionnement
Mounia Hachoumi
 
Return to dlresolve
Return to dlresolveReturn to dlresolve
Return to dlresolve
Angel Boy
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程
Weber Tsai
 
Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation
Angel Boy
 
Binary codes
Binary codesBinary codes
Binary codes
GargiKhanna1
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
Seok-joon Yun
 
Algoritma pencarian (searching algorithm)
Algoritma pencarian (searching algorithm)Algoritma pencarian (searching algorithm)
Algoritma pencarian (searching algorithm)Muhammad Martayuda
 
Digital principles basic
Digital principles basicDigital principles basic
Digital principles basic
Abinaya B
 
Cours de stratégies d'internationalisation
Cours de stratégies d'internationalisation Cours de stratégies d'internationalisation
Cours de stratégies d'internationalisation
musand281
 

What's hot (20)

7 leviers pour générer du trafic en Point de Vente
7 leviers pour générer du trafic en Point de Vente7 leviers pour générer du trafic en Point de Vente
7 leviers pour générer du trafic en Point de Vente
 
Communication et le luxe
Communication et le luxeCommunication et le luxe
Communication et le luxe
 
Etude identité visuelle France Culture Papiers
Etude identité visuelle France Culture PapiersEtude identité visuelle France Culture Papiers
Etude identité visuelle France Culture Papiers
 
Heuristic search-best-first-search
Heuristic search-best-first-searchHeuristic search-best-first-search
Heuristic search-best-first-search
 
Linux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflowLinux Binary Exploitation - Stack buffer overflow
Linux Binary Exploitation - Stack buffer overflow
 
21 citations inspirantes sur l'Inbound Marketing
21 citations inspirantes sur l'Inbound Marketing21 citations inspirantes sur l'Inbound Marketing
21 citations inspirantes sur l'Inbound Marketing
 
Linux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend ProgramingLinux Binary Exploitation - Return-oritend Programing
Linux Binary Exploitation - Return-oritend Programing
 
Penggunaan loop sebagai kerangka dasar algoritma
Penggunaan loop sebagai kerangka dasar algoritma Penggunaan loop sebagai kerangka dasar algoritma
Penggunaan loop sebagai kerangka dasar algoritma
 
Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)Windows 10 Nt Heap Exploitation (Chinese version)
Windows 10 Nt Heap Exploitation (Chinese version)
 
L'écosystème du PO à travers le corps humain par Denis St-Michel
L'écosystème du PO à travers le corps humain par Denis St-MichelL'écosystème du PO à travers le corps humain par Denis St-Michel
L'écosystème du PO à travers le corps humain par Denis St-Michel
 
mencari nilai minimum menggunakan fungsi rekursif di C
mencari nilai minimum menggunakan fungsi rekursif di Cmencari nilai minimum menggunakan fungsi rekursif di C
mencari nilai minimum menggunakan fungsi rekursif di C
 
Positionnement
PositionnementPositionnement
Positionnement
 
Return to dlresolve
Return to dlresolveReturn to dlresolve
Return to dlresolve
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程
 
Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation Linux Binary Exploitation - Heap Exploitation
Linux Binary Exploitation - Heap Exploitation
 
Binary codes
Binary codesBinary codes
Binary codes
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
 
Algoritma pencarian (searching algorithm)
Algoritma pencarian (searching algorithm)Algoritma pencarian (searching algorithm)
Algoritma pencarian (searching algorithm)
 
Digital principles basic
Digital principles basicDigital principles basic
Digital principles basic
 
Cours de stratégies d'internationalisation
Cours de stratégies d'internationalisation Cours de stratégies d'internationalisation
Cours de stratégies d'internationalisation
 

Similar to C dilinde dinamik bellek yönetimi

Heap Overflow Zafiyetleri & Exploiting
Heap Overflow Zafiyetleri & ExploitingHeap Overflow Zafiyetleri & Exploiting
Heap Overflow Zafiyetleri & Exploiting
SignalSEC Ltd.
 
Ileri seviye javascript by Azer Koculu
Ileri seviye javascript by Azer KoculuIleri seviye javascript by Azer Koculu
Ileri seviye javascript by Azer Koculu
mustafa sarac
 
1. Pythonda Sayılar.pdf
1. Pythonda Sayılar.pdf1. Pythonda Sayılar.pdf
1. Pythonda Sayılar.pdf
Anonymousc1QPi2tiK
 
Matlab
MatlabMatlab

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

XMPP ile OTR Kullanımı
XMPP ile OTR KullanımıXMPP ile OTR Kullanımı
XMPP ile OTR Kullanımı
MehmetKelepce
 
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
MehmetKelepce
 
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
MehmetKelepce
 
Zone Transfer Attack
Zone Transfer AttackZone Transfer Attack
Zone Transfer Attack
MehmetKelepce
 
Hedef Odaklı Subdomain Tespiti
Hedef Odaklı Subdomain TespitiHedef Odaklı Subdomain Tespiti
Hedef Odaklı Subdomain Tespiti
MehmetKelepce
 
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ı.
MehmetKelepce
 

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.