C Programlarının Bellek Düzeni ve Değişken Kapsamı

Feyza Ateşoğlu
5 min readDec 20, 2020

--

C programının tipik bellek temsili şu bölümlerden oluşur:

  1. Metin Bölümü (Text Segment)
  2. İlklendirilmiş Veri Bölümü (Initialized Data Segment) (BSS)
  3. İlklendirilmemiş Veri Bölümü (Unitialized Data Segment) (DS)
  4. Stack (Yığın)
  5. Heap (Yığın)
Çalışan bir işlemin tipik bellek düzeni

1.Metin Segmenti

Bir kod parçası veya basitçe metin olarak da bilinen bir metin parçası, bir nesne dosyasındaki veya bellekteki bir programın yürütülebilir talimatlar içeren bölümlerinden biridir.

Bir bellek bölgesi olarak, yığınların ve yığın taşmalarının üzerine yazmasını önlemek için yığının veya yığının altına bir metin parçası yerleştirebiliriz.

Genellikle, metin bölümü paylaşılabilir olduğundan, metin düzenleyicileri, C derleyicisi, kabuklar vb. gibi sık yürütülen programlar için yalnızca tek bir kopyanın bellekte olması gerekir. Ayrıca, bir programın yanlışlıkla talimatlarını değiştirmesini önlemek için metin bölümü genellikle salt okunur( herhangi bir dosya üzerinde değişiklik yapmadan, yalnızca okunabilecek bir yapıya sahip unsur)’dur.

2.İlklendirilmiş Veri Segmenti

Bu veri segmenti, genellikle sadece veri segmenti olarak adlandırılır. Veri segmenti, bir programın sanal adres alanının, programcı tarafından başlatılan global değişkenleri ve statik değişkenlerini içeren bir bölümüdür.

Değişkenlerin değerleri çalışma zamanında değiştirilebileceğinden veri segmentinin salt okunur olmadığını unutmamamız gerekir.

Bu segment, ayrıca başlatılmış salt okunur alan ve başlatılmış okuma-yazma alanı olarak sınıflandırılabilir.

Örneğin, C’de char s[] = “merhaba dünya” ile tanımlanan global dize ve main dışında (yani global) int debug = 1 gibi bir C ifadesi, başlatılmış okuma-yazma alanında depolanır. Ve const char * string = “merhaba dünya” gibi global bir C ifadesi, “merhaba dünya” dizgisinin başlatılmış salt okunur alanda ve karakter işaretçisi değişken dizesinin başlatılmış okuma-yazma alanında depolanmasını sağlar.

Örnek olarak şunu söyleyebiliriz:

static int i = 10 veri segmentinde depolanacak ve global int i = 10 da veri segmentinde depolanacaktır.

3.İlklendirilmemiş Veri Segmenti

“BSS” segmenti olarak adlandırılan ve “sembolle başlatılan blok” anlamına gelen eski bir montajcı operatörünün adını taşıyan başlatılmamış(ilklendirilmemiş) veri segmentidir. Bu segmentteki veriler, program çalışmaya başlamadan önce, çekirdek tarafından aritmetik 0 olarak başlatılır.

İlklendirilmemiş veriler, veri segmentinin sonunda başlar ve sıfırdan başlatılan veya kaynak kodda açık başlatmaya sahip olmayan tüm genel değişkenleri ve statik değişkenleri içerir.

Örneğin bir değişken static int i olarak tanımlanmışsa BSS segmentinde yer alacaktır.
Aynı şekilde global bir değişken int j olarak tanımlanmışsa da BSS segmentinde yer alacaktır.

Yukarıdaki örnek kodda da görüldüğü gibi, ilk önce bir global değişken(global variable) olarak ifade ettiğimiz main fonksiyon(ana fonksiyon) dışına atanan bir değer olarak int data1 değerini tanımladım. Daha sonra ana fonksiyon içine bir statik değer olan static int data2 değerini atadım. Bu iki değişken de BSS segmenti içinde depolanmış oldu.

Yığın(Heap)

Yığın(Heap), genellikle dinamik bellek tahsisinin gerçekleştiği segmenttir .

Yığın alanı, boyutunu ayarlamak için malloc, calloc, free vb. gibi bellek yönetim işlevleri tarafından yönetilir. Malloc ve calloc işlevi kullanılarak biraz daha fazla bellek ayrılması gerektiğinde, yığın yukarı doğru büyür.

  • Yığın alanı, bir işlemdeki tüm paylaşılan kitaplıklar ve dinamik olarak yüklenen modüller tarafından paylaşılır.

Yukarıda örnek olarak verdiğim kodda da görüldüğü gibi malloc işlevini kullanarak yığın segmetinde bellek ayırmış olduk. Ayrıca bu şekilde C programlama dilinde malloc işlevi kullanıldığını da görüyoruz.

Stack (Yığın)

Yığın(Stack) , tüm yerel değişkenleri saklamak için kullanılır ve fonksiyon çağrısı bittikten sonra yürütülecek talimatın dönüş adresi ile birlikte fonksiyonlara argümanlar iletmek için kullanılır . Yerel değişkenler, içinde tanımlandıkları bloğun kapsamına sahiptir, kontrol bloğa girdiğinde oluşturulurlar. Tüm özyinelemeli işlev çağrıları yığına eklenir.

Stack(yığın) ve heap(yığın) geleneksel olarak işlemin sanal adres alanının zıt uçlarında bulunur.

C’DE DEĞİŞKEN KAPSAMI (Variable Scope in C)

Kapsam, programın bir bölgesidir ve değişkenlerin kapsamı, programın bildiriminden sonra değişkenlere erişilebildiği alanı ifade eder.

C’de her değişken kapsamda tanımlanmıştır. Kapsamı, bir değişkenin var olduğu bir programın bölümü veya bölgesi olarak tanımlayabilirsiniz; dahası, bu değişken o bölgenin ötesinde kullanılamaz veya erişilemez.

C programlamasında, bir işlev içinde bildirilen değişken, bir işlevin dışında bildirilen değişkenden farklıdır. Değişken üç yerde tanımlanabilir. Bunlar:

  1. Lokal Değişkenler: Bir fonksiyonun veya bir kod bloğunun içinde tanımlanan değişkenlerdir.
  2. Global Değişkenler: Bir fonksiyon bloğunun dışında bildirilen ve fonksiyonun içinden erişilebilen değişkenlerdir.
  3. Biçimsel Parametreler: Fonksiyon parametrelerinde tanımlanan değişkenlerdir.

YEREL VEYA BLOK KAPSAM (Local or Block Scope)

Yerel bir kapsam veya blok, bir işlev veya blok (küme parantezleri ile çevrili belirli bir bölge) içine yerleştirilen ve bildirilen toplu program ifadeleridir ve bu tür blokların içinde yer alan değişkenler yerel değişkenler olarak adlandırılır. Tüm bu yerel kapsamlı ifadeler yazılır ve sol ({) ve sağ kaşlı ayraçlar (}) kaşlı ayraçlar arasına alınır. C de iç içe bloklar için bir hüküm vardır, bu da başka bir blok veya fonksiyon içinde bir blok veya bir fonksiyon olabileceği anlamına gelir. Bu nedenle, bir blok içinde bildirilen değişken(ler)e o belirli blok ve bu bloğun diğer tüm iç blokları içinden erişilebilir, ancak bu değişkenlere bloğun dışından erişilemediği söylenebilir.

Yerel kapsam için bir örnek verelim:

GLOBAL KAPSAM (Global Scope)

Global değişkenler, çoğu durumda C programının üstünde bir fonksiyonun (main fonksiyonundan önce) veya herhangi bir özel bloğun dışında tanımlanır. Bu değişkenler, değerlerini programın sonuna kadar tutar ve programınızda tanımlanan herhangi bir işlevden erişilebilir.

Herhangi bir işlev, genel kapsam içinde tanımlanan değişkenlere erişebilir, yani kullanılabilirliği, bildirildikten sonra tüm program için kalır.

Yukarıda verdiğim örnek kod ve çıktısına baktığımızda global değişkenimi main fonksiyonu dışına int sum olarak atadığımı görüyoruz. Aynı zamanda bu sum değerini fonksiyonun içinde yazdırabildiğimi (hesaplatabildiğimi) de görüyoruz. Bunun sebebi, daha önce de belirttiğim gibi global değişkenlerin değerlerini program sonuna kadar tutabilmesi ve bu değerlere programımız tarafından tanımlanan herhangi bir işlevden erişilebilmesidir.

GLOBAL DEĞİŞKEN BAŞLATMA (Global Variable Initialization)

Yerel bir değişken tanımladıktan sonra, sistem veya derleyici ona herhangi bir değer vermeyecektir. Kendiniz başlatmalısınız. Kullanmadan önce değişkenleri başlatmak iyi bir programlama uygulaması olarak kabul edilir. Buna karşılık, global değişkenler, tanımlandığı şekilde derleyici tarafından otomatik olarak başlatılır. Veri türüne göre şu şekilde; genel değişkenler tanımlanır:

Son olarak şunu da belirtmek istiyorum, yazımda İngilizce Türkçe karmaşası var gibi görünüyor olabilir. Bence bu konuları Türkçe anlatmak çok daha zor çünkü kavramları karşılayacak kelimeleri seçebilmek gerçekten zor oluyor. Bu yüzden bazı kavramların yanına daha anlaşılabilir olması için İngilizce karşılığını da eklemek istedim. Umarım anlaşılır olmuştur.

Referanslarım: https://www.geeksforgeeks.org/memory-layout-of-c-program/

https://www.w3schools.in/c-tutorial/variable-scope/#:~:text=In%20C%20every%20variable%20defined,or%20accessed%20beyond%20that%20region.&text=Inside%20a%20function%20or%20a%20block.&text=Out%20of%20all%20functions.

--

--

No responses yet