Değişkenler program yığında nasıl saklanır ve alınır?


47

Bu sorunun naifliği için şimdiden özür dilerim. Bilgisayarları ilk kez doğru bir şekilde anlamaya çalışan 50 yaşında bir sanatçıyım. Yani işte gidiyor.

Veri türlerinin ve değişkenlerinin bir derleyici tarafından nasıl işlendiğini anlamaya çalışıyorum (çok genel anlamda, bunun çok fazla olduğunu biliyorum). "Yığın" içindeki depolama ve değer türleri arasındaki ilişkiyi ve "yığın" üzerindeki depolama ile referans türleri arasındaki ilişkiyi anlamamda bir şey eksik; tırnak işaretleri, bu terimlerin soyutlamalar olduğunu anladığımı belirtmek içindir. kelimenin tam anlamıyla bu soruyu çerçevelendirme biçimim gibi basitleştirilmiş bir bağlamda alınması. Her neyse, benim basit düşüncem, Boolean'lar ve tamsayılar gibi türlerin "yığında" devam etmeleridir, çünkü yapabilirler, çünkü depolama alanı bakımından bilinen varlıklardır ve kapsamları buna göre kolayca kontrol edilir.

Ama anlamadığım şey, yığıntaki değişkenlerin nasıl bir uygulama tarafından okunmasıdır - xtamsayı olarak bildirir ve atarsam , diyelim x = 3ve depolama yığında 3saklanır ve değeri burada saklanır ve sonra aynı işlevi ysöyleyeceğim 4, atadığımı ve sonra xbaşka bir ifadede kullandığımı izleyerek aynı işlevi yerine getiriyorum (say z = 5 + x) programın aşağıda ne zaman olduğunu xdeğerlendirmek için nasıl okuyabilirzyyığında? Açıkça bir şey eksik. Yığındaki konumun yalnızca değişkenin kullanım ömrü / kapsamı ile ilgili olduğu ve tüm yığının programa her zaman gerçekten erişilebildiği mi? Öyleyse, değerlerin alınmasına izin vermek için yalnızca yığıntaki adreslerin adreslerini tutan başka bir dizin var mıdır? Ama sonra yığının asıl amacının, değerlerin değişken adresiyle aynı yerde depolanması olduğunu düşündüm. Benim cılız aklımda bu başka bir dizin varsa, o zaman bir yığın gibi daha fazla bir şey hakkında konuşuyorsun görünüyor? Açıkça kafam karıştı ve basit soruma basit bir cevap olduğunu umuyorum.

Bu kadar okuduğunuz için teşekkürler.


7
@ fade2black Katılmıyorum - önemli noktaları özetleyen makul uzunlukta bir cevap vermek mümkün olmalıdır.
David Richerby

9
Sen conflating son derece yaygın hata yapıyoruz değerin tür ile nerede saklandığı . Bools'un yığında olduğunu söylemek yanlış. Bools değişkenlere , ömürleri kısa olduğu biliniyorsa değişkenler yığına , kısa ömürleri bilinmiyorsa yığına giderler . Bunun C # ile nasıl ilgili olduğuna ilişkin bazı düşünceler için bkz. Blogs.msdn.microsoft.com/ericlippert/2010/09/30/…
Eric Lippert

7
Ayrıca, yığını, değişkenlerdeki bir değerler yığını olarak düşünmeyin . Yöntemler için bir aktivasyon kareleri yığını olarak düşünün . Bir yöntem içinde, bu yöntemin aktivasyonunun herhangi bir değişkenine erişebilirsiniz, ancak arayan kişinin değişkenlerine erişemezsiniz, çünkü bunlar yığının tepesindeki karede değildir .
Eric Lippert

5
Ayrıca: Yeni bir şey öğrenmek için inisiyatif aldığınız ve bir dilin uygulama ayrıntılarına girdiğiniz için sizi alkışlarım. Burada ilginç bir tökezleme bloğu ile karşılaşıyorsunuz: soyut bir veri türü olarak bir yığının ne olduğunu anlıyorsunuz , ancak aktivasyonu ve devamı için bir uygulama detayı değil . İkinci etmez değil yığın soyut veri türü kurallarını takip eder; onlara kurallardan çok kurallar gibi davranır. Programlama dillerinin amacı, programlama problemlerini çözmek için bu özet detayları anlamanıza gerek kalmamaktır.
Eric Lippert

4
Teşekkür ederim Eric, Sava, Thumbnail, bu yorum ve referansların hepsi son derece faydalıdır. Her zaman, senin gibi insanların benimki gibi bir soru gördükleri zaman içten içe sızması gerektiğini hissediyorum, ama lütfen cevapları almanın büyük heyecanını ve memnuniyetini bilin!
Celine Atwood

Yanıtlar:


24

Yerel değişkenleri bir yığında depolamak bir uygulama detayıdır - temel olarak bir optimizasyon. Bunu bu şekilde düşünebilirsiniz. Bir işleve girerken, tüm yerel değişkenler için bir yere yer verilir. Daha sonra konumlarını bir şekilde bildiğiniz için tüm değişkenlere erişebilirsiniz (bu tahsisat sürecinin bir parçasıdır). Bir fonksiyondan ayrılırken, alan serbest bırakılır (serbest bırakılır).

Yığın, bu süreci uygulamanın bir yoludur - bunu sınırlı büyüklüğe sahip bir çeşit "hızlı yığın" olarak düşünebilirsiniz ve bu nedenle yalnızca küçük değişkenler için uygundur. Ek bir optimizasyon olarak, tüm yerel değişkenler bir blokta saklanır. Her yerel değişken bilinen bir boyuta sahip olduğundan, bloktaki her bir değişkenin ofsetini bilirsiniz ve bu şekilde erişirsiniz. Bu, adresleri kendilerini diğer değişkenlerde saklayan öbek üzerinde tahsis edilen değişkenlerin aksinedir.

Yığını klasik yığın veri yapısına çok benzer olarak düşünebilirsiniz, çok önemli bir farkla: Yığın tepesinin altındaki öğelere erişmenize izin verilir. Nitekim, erişebileceğiniz üstten inci madde. Tüm yerel değişkenlerinize iterek ve fırlatarak bu şekilde erişebilirsiniz. Yapılan tek itme, işleve girmek ve işlevin ayrılması üzerine gelen tek eylemdir.k

Son olarak, pratikte, yerel değişkenlerin bazılarının kayıtlarda depolandığını söyleyeyim. Bunun nedeni, kayıtlara erişimin yığına erişimden daha hızlı olmasıdır. Bu, yerel değişkenler için boşluk uygulamanın başka bir yoludur. Bir kez daha, bir değişkenin tam olarak nerede depolandığını biliyoruz (bu sefer ofset üzerinden değil, bir kayıt adı aracılığıyla) ve bu tür bir depolama sadece küçük veriler için uygundur.


1
"Bir blokta tahsis" başka bir uygulama detayıdır. Yine de önemli değil. Derleyici, yerel değişkenler için belleğin nasıl gerekli olduğunu bilir, o belleği bir veya daha fazla bloka ayırır ve ardından o bellekte yerel değişkenleri oluşturur.
MSalters

Teşekkürler düzeltildi. Aslında, bu "blokların" sadece bir kısmı kayıtlardır.
Yuval Filmus,

1
Yalnızca eğer dönüş adreslerini saklamak için yığına ihtiyacınız var. Bir işaretleyiciyi öbek üzerindeki dönüş adresine getirerek bir yığın olmadan kolayca yinelemeyi uygulayabilirsiniz.
Yuval Filmus,

1
@MikeCaron Yığınlarının özyineleme ile ilgisi yok neredeyse. Diğer uygulama stratejilerinde neden "değişkenleri yok ettin"?
gardenhead

1
@gardenhead en belirgin alternatif (ve gerçekte kullanılan / kullanılan) her prosedürün değişkenlerini statik olarak tahsis etmektir. Hızlı, basit, tahmin edilebilir ... ancak özyinelemeye veya tekrar girmeye izin verilmez. Bu ve konvansiyonel yığın elbette ki tek alternatif değildir (her şeyi dinamik olarak ayırmak başka bir şeydir), ancak genellikle yığınları haklı çıkarırken tartışılacak olanları onlardır :)
Ocak

23

yYığın üzerinde olması fiziksel xolarak erişilmesini engellemez ; bu, belirttiğiniz gibi, bilgisayar yığınlarını diğer yığınlardan farklı kılar.

Bir program derlendiğinde, yığın içerisindeki değişkenlerin pozisyonları da önceden tanımlanır (bir fonksiyonun bağlamında). Senin örnekte, yığın bir içeriyorsa xile yo, o programın bilir "üstünde" önceden o x1 adet yığının en üstüne altında olacaktır işlevi içinde iken. Bilgisayar donanımı açıkça yığının üstünde 1 öğe isteyebildiğinden, bilgisayar da var xolsa bile alabilir y.

Yığındaki konumun yalnızca değişkenin kullanım ömrü / kapsamı ile ilgili olduğu ve tüm yığının programa her zaman gerçekten erişilebildiği mi?

Evet. Bir işlevden çıktığınızda, yığın işaretçisi etkin bir şekilde silerek önceki konumuna geri döner xve yteknik olarak bellek başka bir şey için kullanılana kadar orada olurlar. Ek olarak, eğer fonksiyonunuz başka bir fonksiyon çağırırsa, xve yhala orada olacak ve isteyerek istifte çok aşağı inerek erişilebilir.


1
Bu, OP'nin masaya getirdiği arka plan bilgisinin ötesinde konuşmama konusundaki en net cevaba benziyor. Gerçekten OP hedeflemesi için +1!
Ben I.,

1
Ben de katılıyorum! Tüm cevaplar son derece yararlı olmasına rağmen çok minnettar olmama rağmen, asıl gönderim motive edildi, çünkü (d) bu yığın / yığın ögesinin değer / referans türü ayrımının nasıl ortaya çıktığını anlamak için kesinlikle temel olduğunu düşündüm, ancak yapamadım ' t "Yığın" ın yalnızca bir kısmını görebilir misiniz? Yani cevabınız beni bundan kurtarıyor. (Fizikteki tüm ters kare yasalarının ilk kez bir küreden çıkan radyasyon geometrisinden düştüğünü fark ettiğimde aldığım aynı hissi alıyorum ve bunu görmek için basit bir diyagram çizebilirsiniz.)
Celine Atwood

Bunu seviyorum, çünkü bazı fenomenlerin neden daha yüksek bir seviyedeki (örneğin, dilde) gerçekten ve soyutlama ağacının biraz altındaki daha basit bir fenomenden kaynaklandığını görmeniz her zaman son derece yararlıdır. Oldukça basit tutulmuş olsa bile.
Celine Atwood

1
@CelineAtwood Yığınlardan çıkarıldıktan sonra "zorla" değişkenlere erişmeye çalışmanın size öngörülemeyen / tanımsız davranışlar vereceğini ve yapılmaması gerektiğini lütfen unutmayın. Bazı dillerde b / c "yapamam" demediğime dikkat edin, denemenize izin verecek. Yine de, bir programlama hatası olurdu ve kaçınılması gerekir.
code_dredd

12

Bir derleyicinin yığını nasıl yönettiğine ve yığın üzerindeki değerlere nasıl erişildiğinin somut bir örneğini vermek için görsel tasvirlere, ayrıca GCCLinux ortamında i386 ile hedef mimari olarak oluşturulan kodlara bakabiliriz .

1. Yığın çerçeveler

Bildiğiniz gibi, yığın, işlev veya yordamlar tarafından kullanılan, işlem için kullanılan argümanların yanı sıra, yerel olarak bildirilen değişkenler için boşluğa yığın tahsis edildiği anlamında çalışan bir işlemin adres alanındaki bir konumdur. Herhangi bir fonksiyonun dışında bildirilen değişkenler için boşluk (yani global değişkenler) sanal bellekte farklı bir bölgede tahsis edilir). Bir fonksiyonun tüm verileri için ayrılan alan bir yığın çerçeveye yönlendirilir . Birden fazla yığın çerçevesinin görsel bir tasviri ( Bilgisayar Sistemlerinden: Bir Programcının Bakış Açısı ):

CSAPP yığın çerçevesi

2. Yığın çerçeve yönetimi ve değişken konum

Belirli bir yığın çerçevesi içinde yığına yazılan değerlerin, derleyici tarafından yönetilmesi ve program tarafından okunması için, bu değerlerin konumlarını hesaplamak ve hafıza adreslerini almak için bazı yöntemler bulunmalıdır. CPU'daki kayıtlar yığın işaretçisi ve temel işaretçi olarak adlandırılır.

Temel işaretçi, ebpkurallara göre, yığının tabanının veya tabanının bellek adresini içerir. Yığın çerçevesindeki tüm değerlerin konumları, referans olarak taban göstergesindeki adres kullanılarak hesaplanabilir. Bu, yukarıdaki resimde tasvir edilmiştir: %ebp + 4örneğin, temel göstergede artı 4'te depolanan hafıza adresidir.

3. Derleyici tarafından oluşturulan kod

Ama anlamadığım şey, yığıntaki değişkenlerin nasıl bir uygulama tarafından okunmasıdır - eğer x'i bir tamsayı olarak ilan edip atarsam, x = 3 deyin ve depoda yığın ayrılır ve sonra 3 değeri saklanır. orada, ve sonra aynı fonksiyonda y olarak 4 deyim ve y olarak bildiririm ve sonra başka bir ifadede x kullandığımı izler, (z = 5 + x diyelim) program z'yi değerlendirmek için x değerini nasıl okuyabilir? yığında y'nin altında mı?

Bunun nasıl çalıştığını görmek için C ile yazılmış basit bir örnek program kullanalım:

int main(void)
{
        int x = 3;
        int y = 4;
        int z = 5 + x;

        return 0;
}

Bu C kaynak metin için GCC tarafından üretilen montaj metnini inceleyelim (netlik amacıyla biraz temizledim):

main:
    pushl   %ebp              # save previous frame's base address on stack
    movl    %esp, %ebp        # use current address of stack pointer as new frame base address
    subl    $16, %esp         # allocate 16 bytes of space on stack for function data
    movl    $3, -12(%ebp)     # variable x at address %ebp - 12
    movl    $4, -8(%ebp)      # variable y at address %ebp - 8
    movl    -12(%ebp), %eax   # write x to register %eax
    addl    $5, %eax          # x + 5 = 9
    movl    %eax, -4(%ebp)    # write 9 to address %ebp - 4 - this is z
    movl    $0, %eax
    leave

Ne gözlemlemek değişkenler x, y ve z adreslerinde yer olmasıdır %ebp - 12, %ebp -8ve %ebp - 4sırasıyla. Başka bir deyişle, yığın çerçevesindeki değişkenlerin yerleri main()CPU kaydına kaydedilen bellek adresi kullanılarak hesaplanır %ebp.

4. Yığın işaretçisinin ötesindeki bellekteki veriler kapsam dışındadır.

Açıkça bir şey eksik. Yığındaki konumun yalnızca değişkenin kullanım ömrü / kapsamı ile ilgili olduğu ve tüm yığının programa her zaman gerçekten erişilebildiği mi? Öyleyse, değerlerin alınmasına izin vermek için yalnızca yığıntaki adreslerin adreslerini tutan başka bir dizin var mıdır? Ama sonra yığının asıl amacının, değerlerin değişken adresiyle aynı yerde depolanması olduğunu düşündüm.

Yığın, sanal bellekteki kullanımı derleyici tarafından yönetilen bir bölgedir. Derleyici, kod işaretçisini, yığın işaretçisinin ötesindeki değerlere (yığının üst kısmındaki değerler) hiçbir zaman referans verilmeyen şekilde oluşturur. Bir işlev çağrıldığında, yığın işaretçisinin pozisyonu, tabiri caizse, "sınırların dışında" olmadığı düşünülen yığında boşluk yaratmak üzere değişir.

İşlevler çağrıldığında ve döndürüldüğünde, yığın işaretçisi azaltılır ve artırılır. Yığına yazılan veriler kapsam dışı olduktan sonra kaybolmaz, ancak derleyici bu verileri referans alarak yönergeler üretmez, çünkü derleyicinin %ebpveya kullanarak bu verilerin adreslerini hesaplaması mümkün değildir %esp.

5. Özet

CPU tarafından doğrudan çalıştırılabilen kod, derleyici tarafından oluşturulur. Derleyici yığını yönetir, işlevler için yığını çerçeveler ve CPU kayıtlarını yönetir. GCC tarafından, i386 mimarisinde çalıştırılmak istenen koddaki yığın çerçevelerindeki değişkenlerin konumlarını izlemek için kullanılan bir strateji %ebp, referans olarak yığın adresini taban çerçeve işaretçisinde, bellek adresini kullanmak ve değişkenlerin yığın çerçevelerindeki konumlara referans değerleri yazmaktır. adrese olan uzaklık %ebp.


Benimki bu resmin nereden geldiğini sorarsam? Şüpheli tanıdık geliyor ... :-) Eskiden bir ders kitabında olmuş olabilir.
Büyük Ördek

1
nvmd. Ben sadece bağlantıyı gördüm. Düşündüğüm buydu. Bu kitabı paylaşmak için +1.
Büyük Ördek

1
Gcc montaj demosu için +1 :)
flow2k

9

İki özel kayıt vardır: ESP (yığın işaretçisi) ve EBP (temel işaretçisi). Bir prosedür çağrıldığında ilk iki işlem genellikle

push        ebp  
mov         ebp,esp 

İlk işlem yığındaki EBP değerini kaydeder ve ikinci işlem yığın işaretçisinin değerini temel işaretçiye (yerel değişkenlere erişmek için) yükler. Bu yüzden EBP, ESP ile aynı yere işaret ediyor.

Assembler değişken isimlerini EBP ofsetlerine çevirir. Örneğin, iki yerel değişkeniniz varsa x,yve

  x = 1;
  y = 2;
  return x + y;

o zaman gibi bir şeye çevrilebilir

   push        ebp  
   mov         ebp,esp
   mov  DWORD PTR [ ebp + 6],  1   ;x = 1
   mov  DWORD PTR [ ebp + 14], 2   ;y = 2
   mov  eax, [ ebp + 6 ]
   add  [ ebp + 14 ], eax          ; x + y 
   mov  eax, [ ebp + 14 ] 
   ...  

Derleme zamanında ofset değerleri 6 ve 14 hesaplanır.

Bu kabaca nasıl çalıştığıdır. Ayrıntılar için bir derleyici kitabına bakın.


14
Bu intel x86'ya özgüdür. ARM'da, FP (R11) 'in yanı sıra SP (R13) registerı kullanılır. Ve x 86, agresif derleyici olacağı kayıt aracının olmaması olup EBP kullanımı bu ESP elde edilebilir. Bu, EBP ile ilgili tüm adreslemelerin ESP'ye göre çevrilebileceği ve başka bir değişikliğe gerek olmadığı son örnekte açıktır.
MSalters

Her şeyden önce x, y'ye yer açmak için ESP'de bir SUB eksik değil mi?
Hagen von Eitzen

Muhtemelen @HagenvonEitzen. Sadece yığında tahsis edilen değişkenlere donanım kayıtları kullanılarak nasıl erişildiğini açıklamak istedim.
fade2black

Seçmenler, yorumlarınız lütfen !!!
fade2black

8

Kafanızda saklanan yerel değişkenlere, yığının erişim kuralı ile erişilmediğinden kafanız karışmış durumda: First In Last Out veya sadece FILO .

Önemli olan, FILO kuralının , yerel değişkenler yerine işlev çağrısı dizileri ve yığın çerçeveleri için geçerli olmasıdır.

Bir yığın çerçeve nedir?

Bir işleve girdiğinizde, yığın çerçevesi üzerinde, yığın çerçevesi adı verilen bir miktar bellek verilir. İşlevin yerel değişkenleri yığın çerçevesinde saklanır. Yığın çerçevenin boyutunun fonksiyondan fonksiyona değiştiğini hayal edebilirsiniz, çünkü her fonksiyonun farklı yerel numaraları ve sayıları vardır.

Yerel değişkenlerin yığın karesinde nasıl depolandıkları FILO ile ilgisi yoktur. (Yerel değişkenlerinizin kaynak kodunuzdaki görünüm sırası bile, yerel değişkenlerin bu sırada depolanmasını sağlamaz.) İstenilen değerlerin alınabilmesi için istif üzerinde ". Yerel değişkenlerin adresleri tipik olarak, yığın çerçevesinin sınır adresi ve her bir yerel değişkene özgü ofset değerleri gibi bir temel adresle hesaplanır .

Peki bu FILO davranışı ne zaman ortaya çıkıyor?

Şimdi, başka bir işlev çağırırsanız ne olur? Aranan işlevi kendi yığın çerçevesini olmalıdır, ve bu yığın çerçevesi itilmiş yığınında . Yani, arayan işlevinin yığın çerçevesi, arayan işlevinin yığın çerçevesinin üzerine yerleştirilir. Ve bu callee işlevi başka bir işlevi çağırırsa, yığın çerçevesi yine yığının üstüne itilir.

Bir fonksiyon dönerse ne olur? Bir çağrı fonksiyonu, çağrı işlevine geri döndüğünde, çağrı işlevinin yığın çerçevesi, ileride kullanmak üzere boş alan bırakarak yığıntan çıkar.

Yani sorunuzdan:

Yığındaki konumun yalnızca değişkenin kullanım ömrü / kapsamı ile ilgili olduğu ve tüm yığının programa her zaman gerçekten erişilebildiği mi?

Burada oldukça haklısın çünkü yığın çerçevesindeki yerel değişken değerleri işlev döndüğünde gerçekten silinmiyor. Değer orada kalır, ancak depolandığı bellek konumu hiçbir işlevin yığın çerçevesine ait değildir. Diğer fonksiyonlar, konumu içeren ve bu hafıza konumuna başka bir değerin üzerine yazan yığın çerçevesini kazandığında değer silinir.

Öyleyse, yığın yığınından hangi farklılıklar çıkıyor?

Yığın ve öbek, her ikisi de bellekteki boşluğa atıfta bulunan adlar bakımından aynıdır. Hafızasındaki herhangi bir yere adresiyle erişebildiğimiz için, yığın veya yığın içindeki herhangi bir yere erişebilirsiniz.

Fark, bilgisayar sisteminin onları nasıl kullanacağına dair verdiği sözünden geliyor. Dediğiniz gibi, yığın referans tipi içindir. Yığındaki değerlerin belirli bir yığın çerçeveyle ilişkisi olmadığından, değerin kapsamı herhangi bir işleve bağlı değildir. Yerel bir değişken, ancak, bir işlev içinde kapsama aldığı ve her ne olabilir anki işlevin yığın çerçevesinin dışına bulunduğu herhangi bir yerel değişken değerini erişmek, sistem kullanarak bu tür bir davranış, olmaz emin olmak için çalışacağız yığın çerçeveleri. Bu bize yerel değişkenin belirli bir işleve getirildiği gibi bir tür yanılsama verir.


4

Yerel değişkenleri bir dil çalışma zamanı sistemine göre uygulamak için birçok yol vardır. Bir yığın kullanmak, birçok pratik durumda kullanılan ortak bir etkin çözümdür.

Sezgisel olarak, bir yığın işaretçisi spçalışma zamanında (sabit bir adreste veya bir kayıt defterinde tutulur - gerçekten önemli). Her "basma" işleminin yığın göstergesini arttırdığını varsayalım.

Olarak Çekirdeği, derleyici her değişkenin adresini belirler sp - Kburada Ktek değişken, (dolayısıyla derleme zamanında hesaplanabilir) kapsamına bağlı olan bir sabittir.

Burada "yığın" kelimesini gevşek bir şekilde kullandığımızı unutmayın. Bu yığına yalnızca push / pop / top işlemleri ile erişilmez, aynı zamanda kullanılarak erişilir sp - K.

Örneğin, bu sözde kodu düşünün:

procedure f(int x, int y) {
  print(x,y);    // (1)
  if (...) {
    int z=x+y; // (2)
    print(x,y,z);  // (3)
  }
  print(x,y); // (4)
  return;
}

İşlem çağrıldığında, argümanlar x,yyığında iletilebilir. Basit olması için, konvansiyonun arayanın xönce bastırdığını varsayalım y.

Daha sonra, nokta (1) en derleyici bulabilirsiniz xde sp - 2ve yde sp - 1.

(2) noktasında, yeni bir değişken kapsam içine alınmıştır. Derleyici toplayan x+y, yani işaret ettiği sp - 2ve sp - 1yığındaki toplamın sonucunu zorlayan bir kod oluşturur .

(3) noktasında z, yazdırılır. Derleyici bunun kapsamdaki son değişken olduğunu bilir, bu nedenle işaret eder sp - 1. Bu artık değişmedi yberi sp. Yine de, yderleyici yazdırmak için bu kapsamda adresinde bulabildiğini biliyor sp - 2. Benzer şekilde, xşimdi bulunur sp - 3.

(4) noktasında kapsamdan çıkarız. zatılır ve yyine adreste bulunur sp - 1ve xadresindedir sp - 2.

Geri döndüğümüzde, ya farayan kişi x,yyığından çıkar .

Dolayısıyla, Kderleyici için hesaplama , kabaca kaç değişkenin kapsamda olduğunu sayma konusudur. Gerçek dünyada, bu aslında daha karmaşıktır çünkü tüm değişkenler aynı boyuta sahip değildir, bu yüzden hesaplamaları Kbiraz daha karmaşıktır. Bazen yığın aynı zamanda dönüş adresini de içerir f, bu yüzden Kde "atlamalı" olmalıdır. Ancak bunlar teknikler.

Bazı programlama dillerinde, daha karmaşık özelliklerin kullanılması gerektiğinde işlerin daha da karmaşık hale gelebileceğini unutmayın. Örneğin, iç içe geçmiş prosedürler çok dikkatli bir analiz gerektirir, çünkü Kşimdi iç içe geçmiş yordam özyineliyse, birçok dönüş adresini "atlamak" gerekir. Kapaklar / lambdas / anonim işlevler de “yakalanan” değişkenleri ele almak için biraz özen gerektirir. Yine de, yukarıdaki örnek temel fikri açıklamalıdır.


3

En kolay fikir, değişkenleri bellekteki adresler için sabit adlar olarak düşünmektir . Aslında, bazı montajcılar makine kodunu bu şekilde görüntüler ("adres 5 değerini adrese kaydet i"), burada ideğişken adıdır).

Bu adreslerin bazıları "mutlak", global değişkenler gibi, bazıları ise "görecelidir", yerel değişkenler gibi. İşlevlerdeki değişkenler (yani adres), her işlev çağrısı için farklı olan "yığın" üzerindeki bir yere göredir; bu şekilde aynı isim farklı gerçek nesnelere atıfta bulunabilir ve aynı işleve yapılan dairesel çağrılar bağımsız bellek üzerinde çalışan bağımsız çağrılardır.


2

Yığına gidebilecek veri öğeleri yığına yerleştirilir - Evet! Bu premium bir alan. Ayrıca, Bir kez xyığına ittikten ve yığına ittikten sonra y, ideal xolana kadar erişemeyiz y. Biz pop gerek yerişmek için x. Onları doğru yaptın.

Yığın değişkenlerden değil, frames

Yanlış anladığın yerde yığının kendisi var. Yığında doğrudan itilen veri öğeleri değil. Aksine, yığında denilen bir stack-frameşey itilir. Bu yığın çerçevesi veri öğelerini içerir . Yığın içindeki karelere erişemezken, üst kareye ve içindeki tüm veri öğelerine erişebilirsiniz.

Diyelim ki veri kalemlerimizi iki yığın çerçevede topladık frame-xve frame-y. Onları birbiri ardına ittik. En frame-yüste oturduğu sürece, frame-xiçindeki herhangi bir veri öğesine ideal olarak erişemezsiniz frame-x. Sadece frame-ygörülebilir. AMA frame-ygörünür olduğu göz önüne alındığında, içindeki tüm veri öğelerine erişebilirsiniz. Çerçevenin tamamı, içerdiği tüm veri öğelerini ortaya çıkarırken görülebilir.

Cevabın sonu. Bu kareler hakkında daha fazla (rant)

Derleme sırasında programdaki tüm fonksiyonların bir listesi yapılır. Daha sonra her fonksiyon için istiflenebilir veri maddelerinin bir listesi yapılır. Sonra her fonksiyon için a stack-frame-templateyapılır. Bu şablon, tüm bu seçilmiş değişkenlerin, işlevin veri girişi için alan, çıkış verileri vb Şimdi bir fonksiyonu olarak adlandırılan her çalışma sırasında içeren bir veri yapısıdır, bu bir kopyası templateyığında konur - birlikte tüm giriş ve ara değişkenlerle . Bu işlev başka bir işlevi çağırdığında, bu işlevin yeni bir kopyası stack-frameyığına alınır. Gibi şimdi de uzun olduğu fonksiyon çalışırken, bu işlevin veri öğelerini korunur. Bir kez bu fonksiyon uçları, yığın çerçeve üzerinden uzattı. şimdibu yığın çerçevesi etkin ve bu işlev tüm değişkenlerine erişebilir.

Bir yığın çerçevenin yapısının ve kompozisyonunun programlama dilinden programlama diline kadar değiştiğini unutmayın. Bir dilde bile, farklı uygulamalarda ince farklılıklar olabilir.


CS'yi düşündüğünüz için teşekkür ederiz. Ben artık bir gün piyano dersleri alan bir programcıyım :)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.