Kısaca yığın çerçeve kavramını açıklar


201

Görünüşe göre programlama dili tasarımında çağrı yığını fikrini alıyorum . Ama yığın çerçevesinin ne olduğuna dair iyi bir açıklama bulamıyorum (muhtemelen, yeterince sert arama yapamıyorum) .

Bu yüzden birinden birkaç kelimeyle bana açıklamasını istemek istiyorum.

Yanıtlar:


195

Yığın çerçevesi, yığının üzerine itilen bir veri çerçevesidir. Çağrı yığını durumunda, yığın çerçevesi bir işlev çağrısını ve bağımsız değişken verilerini temsil eder.

Doğru hatırlarsam, işlev dönüş adresi önce yığına, ardından yerel değişkenler için bağımsız değişkenlere ve alana itilir. Birlikte, muhtemelen mimariye bağlı olsa da, "çerçeve" yaparlar. İşlemci, her karede kaç bayt olduğunu bilir ve kareler itilir ve yığından çıkarılırken yığın işaretçisini buna göre hareket ettirir.

DÜZENLE:

Üst düzey çağrı yığınları ile işlemcinin çağrı yığını arasında büyük bir fark vardır.

Bir işlemcinin çağrı yığını hakkında konuştuğumuzda , montaj veya makine kodunda bayt / kelime düzeyinde adresler ve değerlerle çalışmaktan bahsediyoruz . Üst düzey diller hakkında konuşurken "çağrı yığınları" vardır, ancak bunlar programınızla (yüksek düzeyde) neyin yanlış gittiğini kaydedebilmeniz için çalışma ortamı tarafından yönetilen bir hata ayıklama / çalışma zamanı aracıdır. Bu düzeyde, satır numaraları, yöntem ve sınıf adları gibi şeyler genellikle bilinir. İşlemci kodu aldığında, kesinlikle bu şeyler hakkında hiçbir fikri yoktur.


6
"İşlemci, her karede kaç bayt olduğunu bilir ve kareler itilir ve yığından çıkarılırken yığın işaretçisini buna göre hareket ettirir." - İşlemcinin yığın hakkında bir şey bildiğinden şüpheliyim, çünkü onu subbing (ayırma), itme ve haşhaş ile manipüle ediyoruz. Ve işte, yığını nasıl kullanmamız gerektiğini açıklayan kurallar.
Victor Polevoy

79

Yığını çok iyi anlarsanız, belleğin programda nasıl çalıştığını anlarsınız ve belleğin programda nasıl çalıştığını anlarsanız, programda fonksiyon deposunun nasıl çalıştığını anlarsınız ve programdaki fonksiyon deposunun nasıl olduğunu anlarsanız, özyinelemeli fonksiyonun nasıl çalıştığını ve özyinelemeli işlevin nasıl çalıştığını anlarsınız, derleyicinin nasıl çalıştığını anlarsınız ve derleyicinin nasıl çalıştığını anlarsanız zihniniz derleyici olarak çalışır ve herhangi bir programı çok kolay hata ayıklarsınız

Yığın nasıl çalıştığını açıklayayım:

İlk önce fonksiyonların yığın halinde nasıl temsil edildiğini bilmelisiniz:

Yığın dinamik olarak ayrılan değerleri saklar.
Yığın, otomatik ayırma ve silme değerlerini saklar.

resim açıklamasını buraya girin

Örnekle anlayalım:

def hello(x):
    if x==1:
        return "op"
    else:
        u=1
        e=12
        s=hello(x-1)
        e+=1
        print(s)
        print(x)
        u+=1
    return e

hello(4)

Şimdi bu programın bölümlerini anlayın:

resim açıklamasını buraya girin

Şimdi yığının ne olduğunu ve yığın parçalarının neler olduğunu görelim:

resim açıklamasını buraya girin

Yığın tahsisi:

Bir şeyi hatırlayın: herhangi bir işlevin dönüş koşulu yerine getirilirse, yerel değişkenleri yüklese de yüklemeseniz de, yığın çerçevesiyle derhal yığından dönecektir. Bu, herhangi bir özyinelemeli işlev temel koşulu tatmin ettiğinde ve temel koşuldan sonra bir getiri koyduğumuzda, temel koşulun, programın "başka" bölümünde bulunan yerel değişkenleri yüklemek için beklemeyeceği anlamına gelir. Geçerli kareyi hemen bir sonraki karenin etkinleştirme kaydında olduğu yığından geri döndürür.

Uygulamaya bakın:

resim açıklamasını buraya girin

Bloğun yeniden yerleştirilmesi:

Şimdi bir işlev dönüş ifadesiyle karşılaştığında, geçerli kareyi yığından siler.

Yığından dönerken, değerler yığına ayrıldıkları orijinal sıralamanın tersine döndürülür.

resim açıklamasını buraya girin


3
yığın aşağı doğru büyür ve yığın yukarı doğru büyür, bunları diyagramınızda tersine çevirirsiniz. BURADA DOĞRU ŞEMA
Rafael

@Rafael karışıklık için özür dilerim, büyüme yönünden bahsediyordum, yığın büyümesinin yönü hakkında konuşmuyordum. Büyüme yönü ile yığın büyüme yönü arasında fark vardır. Bkz. Burada stackoverflow.com/questions/1677415/…
Aaditya Ura

2
Rafael haklı. Ayrıca ilk resim yanlış. Başka bir şeyle değiştirin (google resimlerinde "yığın yığını" için arama yapın).
Nikos

Eğer doğru anlarsam, üçüncü şemanızda 3 yığın çerçeve vardır, çünkü hello()yinelenen olarak çağrılır hello(), o zaman (tekrar) özyinelemeli olarak çağrılır hello()ve küresel çerçeve ilk olarak adlandırılan orijinal işlevdir hello()?
Andy J

1
Linkler bizi nereye götürüyor? Güvenlik konusunda ciddi bir endişe olması nedeniyle, bu bağlantılar mümkün olan en kısa sürede kaldırılmalıdır.
Shivanshu

45

Hızlı bir sargı. Belki birinin daha iyi bir açıklaması vardır.

Bir çağrı yığını, 1 veya daha fazla sayıda yığın çerçevesinden oluşur. Her yığın çerçevesi, henüz bir dönüşle sonlandırılmamış bir işleve veya prosedüre yapılan çağrıya karşılık gelir.

Bir yığın çerçevesi kullanmak için, bir iş parçacığı iki işaretçi tutar, bunlardan biri Yığın İşaretçisi (SP), diğeri de Çerçeve İşaretçisi (FP) olarak adlandırılır. SP her zaman yığının "üst" ini gösterir ve FP her zaman çerçevenin "üst" ini gösterir. Ek olarak, iş parçacığı ayrıca yürütülecek bir sonraki yönerge gösteren bir program sayacı (PC) tutar.

Yığın üzerinde aşağıdakiler saklanır: yerel değişkenler ve geçici aralıklar, geçerli komutun gerçek parametreleri (prosedür, işlev vb.)

Yığının temizlenmesi ile ilgili farklı çağrı kuralları vardır.


7
Altyordamın dönüş adresinin yığına geçtiğini unutmayın.
Tony R

4
Frame Pointer da x86 cinsinden Base Pointer
peterchaula

1
Bir çerçeve işaretçisinin şu anda etkin yordam enkarnasyonu için yığın çerçevenin başlangıcını gösterdiğini vurgulamak isterim.
Sunucu Khalilov

13

"Bir çağrı yığını yığın çerçevelerinden oluşur ..." -  Vikipedi

Yığın çerçevesi, yığına koyduğunuz bir şeydir. Bunlar, çağrılacak altyordamlar hakkında bilgi içeren veri yapılarıdır.


Üzgünüm, wiki'de bunu nasıl özlediğime dair hiçbir fikrim yok. Teşekkürler. Dinamik dillerde, işlevin yerlileri tam olarak bilinmediği için çerçevenin boyutunun sabit bir değer olmadığını doğru anladım mı?
ikostia

Bir çerçevenin boyutu ve doğası büyük ölçüde makinenin mimarisine bağlıdır. Aslında, bir çağrı yığını paradigması mimariye özgüdür. Bildiğim kadarıyla her zaman değişken çünkü farklı işlev çağrıları farklı miktarda argüman verisi olacak.
Tony R

Yığın çerçevesinin boyutunun , işlem yapılırken işlemci tarafından bilinmesi gerektiğini unutmayın . Bu olduğunda, verilerin boyutu zaten belirlenir. Dinamik diller, tıpkı statik diller gibi makine kodunda derlenir, ancak genellikle tam zamanında yapılır, böylece derleyici dinamizmi koruyabilir ve işlemci "bilinen" çerçeve boyutları ile çalışabilir. Üst düzey dilleri, bu şeylerin gerçekte gerçekleştiği makine kodu / montaj ile karıştırmayın.
Tony R

Ancak dinamik dillerin de çağrı yığınları var değil mi? Demek istediğim, eğer Python bazı prosedürleri uygulamak istiyorsa, bu prosedürle ilgili veriler bazı Python tercümanlarının yapısında saklanır, doğru muyum? Yani çağrı yığını sadece düşük bir seviyede mevcut değil.
ikostia

Bu wikipedia makalesinin bir kısmını okuduktan sonra, düzeltilmiş duruyorum (biraz). Yığın çerçevesinin boyutu derleme zamanında bilinmeyebilir . Ancak işlemci, yığın + çerçeve işaretçileriyle çalışırken, boyutların ne olduğunu bilmelidir. Boyut değişken olabilir ama işlemci boyutu biliyor, söylemeye çalıştığım şey bu.
Tony R

5

Programcılar, geniş çerçevede olmayan yığın kareleri hakkında (yalnızca bir işlev çağrısına hizmet eden ve dönüş adresini, bağımsız değişkenleri ve yerel değişkenleri saklayan tek bir varlık olduğu) ancak dar anlamda - terimden stack framesbahsedildiğinde derleyici seçeneklerinin bağlamı.

Sorunun yazarının bunu ifade edip etmediği, ancak derleyici seçenekleri açısından bir yığın çerçeve kavramı, burada diğer yanıtlar tarafından kapsanmayan çok önemli bir konudur.

Örneğin, Microsoft Visual Studio 2015 C / C ++ derleyicisi aşağıdakilerle ilgili şu seçeneğe sahiptir stack frames:

  • / Oy (Kare İşaretçisi İhmali)

GCC aşağıdakilere sahiptir:

  • -fomit-frame-pointer (Kare işaretçisi kaydetme, ayarlama ve geri yükleme yönergelerinden kaçınır; birçok işlevde ekstra bir kayıt kullanılabilir hale getirir. )

Intel C ++ Derleyici aşağıdakilere sahiptir:

  • -fomit-frame-pointer (EBP'nin optimizasyonlarda genel amaçlı kayıt olarak kullanılıp kullanılmayacağını belirler)

Aşağıdaki takma adı olan:

  • / Oy

Delphi aşağıdaki komut satırı seçeneğine sahiptir:

  • - $ W + (Yığın Çerçeveleri Oluştur)

Bu özel anlamda, derleyicinin bakış açısından, bir yığın çerçevesi, rutin için yalnızca girişe ve çıkış kodudur; bu , yığını çapa iter - hata ayıklama ve özel durum işleme için de kullanılabilir. Hata ayıklama araçları, yığın verilerini tarayabilir ve bu çapaları call sitesyığın içinde konumlandırırken , yani işlevlerin adlarını hiyerarşik olarak adlandırıldıkları sırayla görüntülemek için geri çekmek için kullanabilir. Intel mimarisi için öyle push ebp; mov ebp, espya entergiriş için ve mov esp, ebp; pop ebpya leaveçıkış için.

Bu nedenle, bir programcı için derleyici seçenekleri söz konusu olduğunda yığın çerçevesinin ne olduğunu anlamak çok önemlidir - çünkü derleyici bu kodu üretip üretmeyeceğini kontrol edebilir.

Bazı durumlarda, yığın çerçevesi (rutin için giriş ve çıkış kodu) derleyici tarafından çıkarılabilir ve değişkenlere uygun temel işaretçi (BP / ESP / RSP). Yığın çerçevesinin atlanması için koşullar, örneğin:

  • işlev bir yaprak işlevidir (yani, diğer işlevleri çağırmayan bir son varlık);
  • try / nihayet veya try / hariç veya benzer yapılar yoktur, yani istisna kullanılmaz;
  • yığın üzerinde giden parametrelerle hiçbir rutin çağrılmaz;
  • işlevin parametresi yoktur;
  • fonksiyonun satır içi montaj kodu yoktur;
  • vb...

Yığın çerçevelerini (rutin için giriş ve çıkış kodu) atlamak kodu daha küçük ve daha hızlı yapabilir, ancak hata ayıklayıcıların yığındaki verileri geri izleme ve programcıya görüntüleme yeteneğini de olumsuz etkileyebilir. Bunlar, bir fonksiyonun hangi koşullar altında giriş ve çıkış koduna sahip olması gerektiğini belirleyen derleyici seçenekleridir, örneğin: (a) her zaman, (b) asla, (c) gerektiğinde (koşulları belirterek).


-1

Yığın çerçevesi, işlev çağrısıyla ilgili paketlenmiş bilgidir. Bu bilgiler genellikle işleve iletilen bağımsız değişkenleri, yerel değişkenleri ve sonlandırıldıktan sonra nereye dönüleceğini içerir. Aktivasyon kaydı, yığın çerçevesi için başka bir isimdir. Yığın çerçevesinin yerleşimi ABI'de üretici tarafından belirlenir ve ISA'yı destekleyen her derleyici bu standarda uygun olmalıdır, ancak yerleşim şeması derleyiciye bağlı olabilir. Genellikle yığın çerçeve boyutu sınırlı değildir ancak sistem çağrılarının ... vb. Yığın çerçevesine müdahale etmeden yürütülmesine izin vermek için "kırmızı / korumalı bölge" adı verilen bir kavram vardır.

Her zaman bir SP vardır, ancak bazı ABI'lerde (örneğin ARM'ler ve PowerPC'ler) FP isteğe bağlıdır. Yığına yerleştirilmesi gereken bağımsız değişkenler yalnızca SP kullanılarak dengelenebilir. Bir işlev çağrısı için yığın çerçevesinin oluşturulup oluşturulmayacağı, bağımsız değişkenlerin türüne ve sayısına, yerel değişkenlere ve yerel değişkenlere genel olarak nasıl erişildiğine bağlıdır. Çoğu ISA'da ilk olarak kayıtlar kullanılır ve argümanları iletmek için ayrılmış kayıtlardan daha fazla argüman varsa bunlar yığına yerleştirilir (Örneğin x86 ABI'de tamsayı argümanlarını iletmek için 6 kaydı vardır). Bu nedenle, bazen, bazı işlevlerin yığına yerleştirilmesi için bir yığın çerçevesine gerek yoktur, yalnızca dönüş adresi yığının üzerine itilir.

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.