Bölge tabanlı bellek yönetimi(region-based memory management), tahsis edilen her nesnenin bellekteki bir bölgeye atandığı bellek yönetimi türüdür.[6]
Bellek bölümü(memory region), nesnelerin tekrar tekrar tahsis edilebildiği bir alandır. Bellek bölümü bellek arenası, bellek alanı, bellek bölgesi olarak da isimlendirilebilirler.
Takip eden görselde bir bellek bölümlendirmesinin örneğini görüyoruz. Bir programın çalışabilmesi için RAM'de yer ayrılması gerekir. Ayrılacak olan bu alan programdaki fonksiyonlar, değişkenler, veriler gibi yapıların kullanımıyla ilişkilir.
Bir bellek; stack, heap, statik veri ve kod bölümlerinden oluşur. Bu yazımızda stack ve heap bölümlerinin ne olduğunu, ne yönlerle birbirlerinden ayrıldıklarını, avantaj ve dezavantajlarını örnekler vererek inceleyeceğiz.
Stack (yığın), LIFO (son eklenen ilk çıkar) mantığında çalışarak veri depolayan sanal bir veri türüdür.[7] push
(ekle) ve pop
(çıkar) şeklindeki iki komut ile yığına veriler eklenir veya çıkarılır. Stack'e eklenen ilk verinin silinmesi sonrasındaki tüm verilerin silinmesine bağlıdır.
Stack'de çöp toplama (garbage collector) işlemi otomatik olarak gerçekleştirilir. Programcının bu konuda herhangi bir adım atmasına gerek yoktur.
Programda fonksiyonlar çağrıldığında fonksiyon içindeki yerel değişkenler (local variables) yığında(stack) tutulur ve fonksiyonun sonlanmasının ardından yok edilir.
Stack'de en altta bulunan veriye erişmeniz için üstündeki tüm verileri kaldırmanız gerekir. push
, verileri eklemenizi sağlarken; pop
, verileri çıkarmanızı sağlar.
Stack ile ilgili olarak örnek bir kod inceleyelim.
# Python ve Stack #bir dizi tanımladık stack = [] # append() fonksiyonunu push(ekleme) işlemi kullanıyoruz. stack.append('S') stack.append('t') stack.append('a') stack.append('c') stack.append('k') print('Şu anda stack: ') print(stack) # pop() fonksiyonunu pop(çıkarma) işlemi için kullanıyoruz. print('\nElemanları LIFO sırasına göre çıkartıyoruz.') print(stack.pop()) print(stack.pop()) print(stack.pop()) print('\nYeni dizimiz:') print(stack)
Kodumuzun çıktısı:
Şu anda stack: ['S', 't', 'a', 'c', 'k'] Elemanları LIFO sırasına göre çıkartıyoruz. k c a Stack after elements are popped: ['S', 't']
Yığın taşması (stack overflow), bir programın bellekte ayrılmış kullanılabilir stack alanının fazlasını kullanmaya çalışması sonucu karşılaşılan problemdir. Veri büyüklüğü doğru şekilde ayarlanmadığı zamanlarda karşımıza çıkmaktadır.
Heap (öbek, yığın), stackten farklı olarak belleğin dinamik olarak tahsis edildiği bellek yönetim türlerinden bir diğeridir. Not olarak, heap isminin heap veri yapısıyla (heap data structure) hiçbir ilişkisi yoktur. [2]
Heap, belleğin doğrudan kontrol edilebildiği bir bellek bölümüdür. Kontrol yetkisi ise programcılara aittir. Tabi hal böyle olunca kontrolün yanlış kullanılması bellek taşması gibi riskli sonuçlar doğurabilir. Programcının heap'i dikkatli şekilde kullanması bu yüzden önemlidir.
Heap'de verilerin büyüklüğü dinamik olarak belirlenir. Örneğin, büyük bir dizi (array) tanımlamak istiyorsunuz ama dizinin büyüklüğünün ne olacağını tam olarak bilmiyorsanız heap kullanmak işinizi kolaylaştıracaktır.
//Dinamik Tahsis (Dynamic Allocation) //C++ dilinde örnek kod #include <iostream> int main() { //Pointer tanımladık. int* ptr; //malloc komutuyla heap'e tahsis ettik. //Büyüklüğünü sizeof(int) ile dinamik yaptık. ptr = (int*) malloc(sizeof(int)); *ptr = 100; //Ekrana yazdırdık. std::cout<<"Pointer: "<<ptr<<std::endl; }
Bir başka örneğimize bakalım.
//Dinamik Tahsis (Dynamic Allocation) //C++ dilinde örnek kod #include <iostream> int * f1 ( ) { //heap de int türünde pointer tanımladık int* ptr = (int*) malloc ( sizeof ( int ) ) ; //pointera değer atadık ve onu döndürdük *ptr = 5 ; return ptr ; } int main(){ //ptr2 f1 fonksiyonunda heap de tutulan ptrnin değerini alacaktır. int * ptr2 = f1 ( ) ; //pointeri ekrana yazdırıyoruz std::cout<<"Pointer: "<<ptr2<<std::endl; //pointerda tutulan int değerini yazdırdık: 5 std::cout<<"Pointer Değeri: "<<*ptr2<<std::endl;
Bellek sızıntısı (memory leak), bir programda artık ihtiyaç duyulmayan verinin serbest bırakılmadığı durumda kaynak kullanıma devam etmesi sonucu meydana gelen bir kaynak sızıntısıdır. Kaynak kodlarına sahip olan programcılar tarafından soruna müdahale edilebilir ve sorun çözülebilir. [8]
#include <iostream> int *degerTahsisEt(){ int* ptr = (int*) malloc(sizeof(int)); return ptr; }; int main() { int i = 0; //Sınırın çok yükseltilmesi sonucu bilgisayarınız beynini yakabilir! int sinir= 1000; while(i < sinir){ //fonksiyon aracılığıyla yeni bir değer tahsis ediyoruz her seferinde int* tahsisEdilenDeger = degerTahsisEt(); //ekrana değeri yazdırdık. std::cout<<":"<<tahsisEdilenDeger<<std::endl; //free fonksiyonuyla heap'deki garbage collector işlemini tamamladık //free komutu olmadığı taktirde RAM şişmeye başlayacaktı ve memory leak durumu..meydana gelebilecekti. free(tahsisEdilenDeger); i++; } }
Stack ve heap'i ayrı ayrı ele aldığımıza göre arasındaki farkları listeleyebiliriz.
- Veri büyüklüğü sabittir. Yani statik değişkenler tutulur.
- Heap'e kıyasla daha hızlıdır.
- Bir bellek bölümüdür.
- Veriler ve işlemler otomatik kontrol edilir.
- LIFO (Last in, first out) mantığında çalışır.
- Değişkenlerin tanımlanmasında pointer'a ihtiyaç yoktur.
- Veriler fonksiyon çağrıldığı anda bellekte tutulur.
- Kolaydır.
- Linear veri türü yapısındadır.
- Veri büyüklüğü dinamik olarak değişir.
- Bir bellek bölümüdür.
- Stack'e kıyasla daha yavaştır.
- Veriler ve işlemlerin kontrolü programcı tarafından yapılır.
- Stackden farklı olarak parçalanmış bir yapıdadır.
- Değişkenlerin tanımlanmasında pointer kullanılır.
- Daha zordur.
- Hierarchical veri türü yapısındadır.
Bir programcının herhangi bir yazılım dilinde sıklıkla karşılaştığı ya da karşılaşacağı kavramlardan Stack ve Heap'i bu yazımızda ele almak istedim. Aklınıza takılan sorular olursa bana ulaşabilirsiniz. Kendinize çok iyi bakın. Sağlıcakla.
Yorumunu Bırak
Yorumlar
0 Yorum yokHenüz yorum yapılmamış. İlk yorum yapan sen ol.