Heap vs Stack

Stack ve Heap Farkı

Mehmet Baran Munar
4 min readMay 23, 2023

Bugün, stack ve heap belleğine hızlı bir şekilde göz atacağız ve uygulamamız çalışırken kodumuzun ve değişkenlerimizin bellekte nasıl saklandığını göreceğiz.

Uygulamamızın hafızası üç ana kısımda saklanır. İlk kısım makine kodudur. Burası, uygulamamızın bilgisayarımızın anlayabileceği talimatlara dönüştürüldüğü yerdir. Sonraki iki kısım ise stack ve heap’tir.

Stack, Heap ve Makine Kodu

Stack’i anlamak için stack veri yapısını anlamamız gerekir. Stack veri yapısı, üst üste yığılmış bir kitap yığınına benzer.

Yığının üstünden bir kitap alabilir veya üstüne bir kitap ekleyebilirsiniz ama yığının geri kalanındakilere erişemezsiniz. Yani ortadan veya alttan bir şey alamayız. Uygulamalarda call stack dediğimiz bir kavram var. Call stack, bilgisayarın çalışma zamanında fonksiyonları veya methodları çağırmak için kullanılır. Call stack bunların sırasını ve dönüş noktalarını takip eder. Bir method çağrıldığında call stack’e yeni bir frame eklenir. Bu kısım, çağrısı yapılan methodun bilgilerini (parametreler, dönüş adresi vs.) içerir. Method çağrısı tamamlandığında, call stack’ten bu kısım çıkarılır ve program, çağrıyı yapan yerden devam eder.

Call Stack

Heap ise stack’in aksine öğeleri bellekte herhangi bir sırada saklamamıza izin verir. Stack’teki gibi en üstten almamıza gerek yok. Herhangi bir yerden erişebiliriz. Heap’e öğe eklemek stack’e öğe eklemekten daha fazla yüke sebep olur.

Stack vs Heap

Heap genellikle, call stack’teki verilerden daha uzun süre yaşayacak verilere ihtiyaç duyulduğunda kullanılır. Eğer farklı methodlar arasında erişilmesi gereken bir değişken veya bir method çalıştıktan sonra erişilebilir olması gereken veriler varsa, bu veriler heap’te yaşayacaktır.

Call stack, programın yürütme sırasında geçici verilerin depolandığı bir bellek alanıdır. Her bir method çağrıldığında, methoda ait değişkenler ve geri dönüş adresi gibi bilgiler call stack’e yerleştirilir. Method sona erdiğinde ise bu veriler yığından kaldırılır ve bellek geri kazanılır. Bu nedenle, call stack’teki veriler yalnızca ilgili method çağrıldığı sürece kullanılabilir ve method sonra erdikten sonra erişilemez hale gelir.

Öte yandan heap, programın çalışma süresi boyunca yaşayan verilerin depolandığı bir bellek alanıdır. Bu bellek alanında oluşturulan veriler, methodların dışında da erişilebilir. Örneğin bir nesne oluşturulduğunda ve bu nesne birden fazla methodda kullanılacaksa, nesne heap belleğinde oluşturulur ve methodlar arasında erişilebilir hale gelir.

Bu kısmı özetlemek gerekirse, eğer verilerinizi farklı methodlar arasında paylaşmanız veya bir method çalıştıktan sonra hâlâ erişilebilir olmaları gerekiyorsa, bu veriler genellikle heap belleğinde tutulur. Call stack ise geçici verilerin depolandığı bir bellek alanı olup yalnızca ilgili yöntem çağrıldığı sürece erişilebilir olmasını sağlar.

Şimdi değişkenlerimizin bellekte nerede depolandığını bulmak için uygulayabileceğimiz bazı genel kurallar var. Integer gibi veri türleri, yalnızca tek bir bellek değeri olarak depolanırken, referans türünün bir değere işaretçisi (pointer) vardır.

Pointer to the reference value

Yani bir referans tipi için iki parçamız var. Genellikle bellekteki bir konumun adresi olan bir işaretçimiz var. Referans türleri için değerler her zaman heap’te saklanır. Değer türleri ise onu nerede deklare ettiğimize bağlıdır. Bir method’ta yerel bir değişken (local variable) oluşturduğumuzda, bu değişkene method dışından erişemeyeceğimizi ve bunun nedenini biliyoruz çünkü bu yerel değişken methodla birlikte çağrıldığında depolanacak. Çağrılma bittiğinde o blok yok olacak, bu nedenle o yerel değişken artık mevcut olmayacak. Her değer tipi stack’te depolanmaz. Bu, onu nerede tanımladığımıza bağlıdır. Global değişken her zaman heap’te depolanır. Çünkü ona kodumuzdaki farklı alanlardan erişebilmemiz gerekir. Örneğin, bir class yaratırsak ve ardından class’ta değişkenler varsa ve bu nedenle o class da heap’te olacaktır. Referans tiplerimiz sadece bellekte bir konum işaretçisine sahip olduğundan methodun yürütülmesi bittikten sonra o bellek bloğuna ne olacağını biliyor muyuz?

Global değişken heap’te depolanır.

Çoğu çalışma zamanında garbage collector dediğimiz şeye sahibiz. Adından da anlaşılacağı gibi, çöp toplayıcı çöp toplamak için etrafta dolaşıyor. Dolaşır ve yığına bakar ve artık kullanılmayan şeyleri bulur ve temizler. Böylece, bir methodda bildirilen bir referans türü artık kullanılmadığında, işaretçi gider ve sonra ona işaret eden hiçbir şey olmadığı için, çöp toplayıcı gelir, onu temizler. Öyleyse, referans türlerine sahip olduğunuz genel kurallar her zaman heap üzerindedir. Değer türleri, nerede bildirildiğine bağlı olarak stack’te veya heap’te bulunur. Son olarak, bir istisna var. Statik değişkenler, kodunuzdaki herhangi bir yerden onlara erişebilmeniz gerektiğinden, her zaman heap’te olacaktır.

Garbage collector

Bu yazıda elimden geldiğince stack ve heap kavramlarını, bu iki kavramın farklarını, call stack kavramını ve garbage collector kavramını anlatmaya çalıştım. Bir sonraki yazımda görüşmek üzere!

--

--