Stack & Heap— C# string vs String vs StringBuilder

Halil İbrahim Kocaöz
3 min readNov 24, 2023

--

Stack ve Heap, bellek için kullanılan iki farklı bellek yönetim türünü ifade eder. C# ile string, String veri tipleri ve StringBuilder classı ile birlikte bu iki bellek yönetim şeklini ele alacağım.

Stack

Stack, local variable, function calls ve pointer gibi sınırlı yaşam süresine sahip verileri saklamak için kullanılır. Verileri LIFO — Last In, First Out (son giren, ilk çıkar) prensibi ile saklar.

Stack, otomatik olarak yönetilir. Local variable ve function calls gibi verilerin yönetimi, işletim sistemi veya programın çalıştığı compiler tarafından otomatik olarak yapılır. Stackte duran verilerin ömrü method & function gibi çağrıların çalışma süresi ile sınırlıdır.

Stack, sınırlı bir kapasiteye sahiptir ve bu kapasite compile edilirken belirlenir. Stack compile zamanında belirlenenden daha fazla veri tutamaz ve bunun aşılması durumunda stack overflow meydana gelir.

Stack, genelde sabit boyutlu variableları (int, char, boolean…) saklamak için kullanılır.

Heap

Heap, yaşam süresi daha uzun olan veya dinamik verilerin saklanması için kullanılır. Heap, verilerin eklenme ve çıkarılma sırasına göre düzenlenmez, bu nedenle Heap üzerinden verilere rastgele bir erişim sağlayabiliriz.

Heap ile memory allocation ve deallocation geliştiricinin sorumluluğundadır. Geliştiriciler Heap üzerinde çalışan kodlarda memory leaks, buffer overflows gibi sorunlardan sorumludur — modern programlama dillerinde bunlar GC tarafından handle edilse de bazı durumlarda yine sorumluluk geliştiricilerdedir.

Heap, geniş bir kapasiteye sahiptir ve kodun çalıştığı sistemin toplam bellek kapasitesine bağlı kalarak ne kadar veri tutabileceğini büyütebilir.

Heap, büyük ve dinamik veri yapılarını (örneğin diziler, karmaşık, birden çok tipde veri barındıran yapılar, listeler) saklamak için daha uygundur.

String & string veri tipleri

String ve string ikisi de aynı işi yapan aralarında bir fark olmayan reference veri tipleridir, fakat değiştirilemezlerdir — immutable bir veri tipidir. Değiştirilemez ne demek diyebilirsiniz. string veri tipinin üzerinde yaptığınız her değişiklik aslında heap bellekte yeni bir alan tutar.

string str = "Merhaba, ";
str += "Dünya!";

Yukarıda gördüğünüz kod, ilk başta ‘Merhaba, ’ yazıyor ardından += işlemi ile ‘Dünya!’ eklemesi yapıyoruz ve bunun sonucunda ‘Merhaba Dünya!’ elde ediyoruz. Aslında bellekte ‘Merhaba, ’ ve ‘Merhaba Dünya!’ stringi için iki yer ayrıldı. İlk başta ‘Merhaba, ’ yazan yer için biraz daha yer ayırıp ardından da Dünya! kısmı eklenmedi.

Aynı şekilde, string veri tipi üzerinde kullandığımız manipülasyon metotlarının hepsi de yeni bir string oluşturur ve bellekte yer tutar.

string str = "Merhaba, Dünya!";
// Merhaba, Dünya!
str = str.Replace("Merhaba", "Selam").ToUpper();
// SELAM DÜNYA!

İlk önce bir eşitlik ile string tanımladık ardından da iki manipülasyon metodu ile verimizi manipüle ettik, toplamda bellekte 3 string objesi için yer tutuldu ama elimizde bir string var.

Sonuç olarak üzerinde manipülasyon yapacağımız herhangi bir metin verisini String veya string olarak tanımladığımız değişkenler üzerinden yapmamalıyız. Bu gereksiz memory allocationlarını string manipülasyonlarında nasıl ele alıyoruz ona bakalım.

StringBuilder classı

StringBuilder classı, string veri tipinin aksine mutable — değiştirilebilirdir. StringBuilder classı ile yaptığınız bir tanımlamanın bellekte tuttuğu yer genişletilebilir, küçültülebilir veya tamamen boşaltılabilir. StringBuilder classı ile metin manipülasyonları string’in aksine bellekte yeni bir obje oluşturmaz, varolan obje için ayrılmış alanda değişiklik yapar veya o alanı genişleterek ekleme yapar.

var strBuilder = new StringBuilder();
strBuilder.Append("Merhaba, ");
strBuilder.Append("Dünya!");

StringBuilder ile oluşturulmuş bir değişkende Append ederek ‘Merhaba Dünya!’ metnini elde ettik. — Aslında ToString diyene kadar metni hala elde etmiyoruz. —
İlk önce 0 kapasite ile bir StringBuilder oluştu, ilk Append ile birlikte StringBuilder’in kapasitesi 9 karaktere arttırıldı ve sırasıyla bizim verdiğimiz metindeki karakterleri oraya yerleştirdi. Sonra tekrardan bir Append yaptık, 9 olan kapasite 15'e çıkarıldı ve sırasıyla bizim verdiğimiz metindeki karakterleri oraya yerleştirdi.

Kısaca StringBuilder classı ile birlikte elimizde olan bir metni gereksiz bir şekilde memory allocation yapmadan manipüle edebildik.

Unlisted

--

--