it-swarm-tr.com

Yığın ve yığın nerede ve nerede?

Programlama dil kitapları yığın 'da değer tiplerinin yaratıldığını ve yığın ' da referans tiplerinin yaratıldığını, bu iki şeyin ne olduğunu açıklamadan açıklar. Bununla ilgili net bir açıklama okumamıştım. A yığınının ne olduğunu biliyorum. Fakat, 

  • nerede ve ne (fiziksel olarak gerçek bir bilgisayarın hafızasında)?
  • İşletim sistemi veya dil çalışma zamanı ne ölçüde kontrol edilir?
  • Kapsamı nedir?
  • Her birinin boyutunu ne belirler?
  • Birini daha hızlı yapan nedir? 
7473
mattshane

Yığın, bir yürütme iş parçacığı için kazıma alanı olarak ayarlanan hafızadır. Bir işlev çağrıldığında, yerel değişkenler ve bazı defter tutma verileri için yığının üstüne bir blok ayrılır. Bu işlev döndüğünde, blok kullanılmaz ve bir dahaki işlev çağrıldığında kullanılabilir. Yığın her zaman LIFO (ilk giren ilk) sırasına ayrılır; en son rezerve edilen blok her zaman serbest bırakılacak bir sonraki bloktur. Bu, yığını takip etmeyi gerçekten kolaylaştırıyor; bir bloğu yığından çıkarmak, bir işaretçiyi ayarlamaktan başka bir şey değildir.

Öbek dinamik ayırma için ayrılan bellektir. Yığının aksine, blokların yığından tahsisine ve ayrılmasına yönelik hiçbir zorunluluk yoktur; bir bloğu istediğiniz zaman tahsis edebilir ve istediğiniz zaman boşaltabilirsiniz. Bu, herhangi bir zamanda yığının hangi kısımlarının tahsis edildiğini veya serbest bırakıldığını takip etmeyi çok daha karmaşık hale getirir; Farklı kullanım şekilleri için yığın performansını ayarlamak üzere kullanılabilen birçok özel yığın ayırıcı vardır.

Her iş parçacığı bir yığın alır, ancak uygulama için genellikle yalnızca bir yığın vardır (farklı ayırma türleri için birden fazla yığın olması nadir değildir).

Sorularınıza doğrudan cevap vermek için: 

İşletim sistemi veya dil çalışma zamanı ne ölçüde kontrol ediliyor?

İşletim sistemi, iş parçacığı oluşturulduğunda her sistem düzeyinde iş parçacığı için yığını ayırır. Genellikle işletim sistemi, öbek için uygulama ayırmak için dil çalışma zamanı tarafından çağrılır.

Kapsamları nedir?

Yığın bir ipliğe tutturulur, böylece yiv çıktığında yığın geri kazanılır. Yığın tipik olarak uygulama başlangıcında çalışma zamanı tarafından atanır ve uygulama (teknik olarak işlemden) çıktığında geri kazanılır.

Her birinin boyutunu ne belirler? 

Bir iş parçacığı oluşturulduğunda yığının boyutu ayarlanır. Yığın boyutu uygulama başlangıcında belirlenir, ancak alan gerektiğinde büyüyebilir (tahsisatçı işletim sisteminden daha fazla bellek ister).

Hangisini daha hızlı yapan nedir?

Yığın daha hızlıdır, çünkü erişim düzeni bellekten ayrılmayı ve ayrılmasını önemsiz kılar (bir işaretçi/tamsayı basitçe artırılır veya azalır), öbür yığın ayırma veya ayırma işlemine dahil olan çok daha karmaşık defter tutma işlemlerine sahiptir. Ayrıca, yığındaki her bir bayt çok sık kullanılmaya meyillidir; bu işlem, işlemcinin önbelleğiyle eşleştirilme eğiliminde olduğu anlamına gelir. Yığın için bir başka performans, çoğunlukla küresel bir kaynak olan yığının tipik olarak çoklu iş parçacığı için güvenli olması gerektiği, yani, her tahsis ve dağıtma işleminin - tipik olarak - programdaki "tüm" diğer yığın erişimleriyle senkronize edilmesi gerektiğidir.

Açık bir gösteri:
Resim kaynağı: vikashazrati.wordpress.com

5529
Jeff Hill

Yığın:

  • Bilgisayarda saklanan RAM tıpkı yığın gibi.
  • Yığında oluşturulan değişkenler kapsam dışına çıkar ve otomatik olarak kaldırılır.
  • Yığındaki değişkenlere kıyasla ayırmak için çok daha hızlı.
  • Gerçek bir yığın veri yapısı ile uygulanır.
  • Parametre geçişinde kullanılan yerel verileri, dönüş adreslerini saklar.
  • Çok fazla yığın kullanıldığında yığın taşması olabilir (çoğunlukla sonsuz veya çok fazla özyinelemeden, çok büyük tahsisatlardan).
  • Yığında oluşturulan veriler, işaretçiler olmadan kullanılabilir.
  • Derleme süresinden önce ne kadar veri ayırmanız gerektiğini tam olarak biliyorsanız yığını kullanacaksınız ve çok büyük değil.
  • Genellikle, programınız başladığında zaten belirlenmiş bir maksimum boyut vardır.

Yığın:

  • Bilgisayarda saklanan RAM tıpkı yığın gibi.
  • C++ 'da, yığıntaki değişkenler elle imha edilmeli ve asla kapsam dışına çıkmamalıdır. Veriler delete, delete[] veya free ile serbest bırakılır.
  • Yığındaki değişkenlere kıyasla ayırmak için daha yavaş.
  • Talep üzerine program tarafından kullanılmak üzere bir veri bloğu tahsis etmek için kullanılır.
  • Çok fazla tahsis ve tahsisat olduğunda, parçalanma olabilir.
  • C++ veya C'de, öbek üzerinde oluşturulan veriler işaretçiler tarafından gösterilecek ve sırasıyla new veya malloc ile ayrılacaktır.
  • Çok büyük bir arabellek tahsis edilmek istenirse tahsisat hataları olabilir.
  • Çalışma zamanında tam olarak ne kadar veriye ihtiyaç duyacağınızı bilmiyorsanız veya çok fazla veri ayırmanız gerekirse, yığını kullanırsınız.
  • Bellek sızıntılarından sorumlu.

Örnek:

int foo()
{
  char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
  bool b = true; // Allocated on the stack.
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
2199
Brian R. Bondy

En önemli nokta, yığın ve yığının, belleğin ayrılabileceği yollar için genel terimler olmasıdır. Bunlar birçok farklı şekilde uygulanabilir ve terimler temel kavramlara uygulanır.

  • Öğeler yığınında, öğeler yerleştirildikleri sırayla üst üste otururlar ve yalnızca üstünü çıkarabilirsiniz (her şeyi devirmeden).

    Stack like a stack of papers

    Bir yığının basitliği, ayrılmış belleğin her bir bölümünün kaydını içeren bir tablo tutmanıza gerek kalmamasıdır; İhtiyacınız olan tek durum bilgisi, yığının sonuna tek bir işaretçidir. Tahsis etmek ve tahsis etmek için, o tek göstericiyi artırıp azaltmanız yeterlidir. Not: Bazen bir bellek bölümünün en üstünde başlamak ve yukarı doğru büyümek yerine aşağı doğru uzanmak için bir yığın uygulanabilir.

  • Bir yığında, öğelerin yerleştirilme şeklini belirli bir düzen yoktur. Açık bir 'üst' öğe olmadığından, herhangi bir sıradaki öğelere ulaşabilir ve bunları kaldırabilirsiniz.

    Heap like a heap of licorice allsorts

    Yığın tahsisi, hangi hafızanın tahsis edildiğine ve neyin ayrılmadığına dair tam bir kayıt tutmayı gerektirir; ayrıca, parçalanmayı azaltmak için bazı genel bakım işlemleri, istenen boyuta sığacak kadar büyük bitişik hafıza bölümleri bulma vb. Bellek, boş alan bırakarak herhangi bir zamanda dağıtılabilir. Bazen bir bellek ayırıcısı, tahsis edilen belleği etrafa taşıyarak belleği birleştirmek veya çöp toplamak gibi işlemleri gerçekleştirir - belleğin artık kapsam dahilinde olmadığı ve çalışma zamanının kaldırılacağı zaman. 

Bu görüntüler, bir yığın ve bir yığında bellek ayırmanın ve boşaltmanın iki yolunu açıklamak için oldukça iyi bir iş çıkarmalıdır. Yum!

  • İşletim sistemi veya dil çalışma zamanı ne ölçüde kontrol edilir?

    Belirtildiği gibi, yığın ve yığın genel terimlerdir ve birçok şekilde uygulanabilir. Bilgisayar programları, tipik olarak, hangi fonksiyondan çağrıldığına dair bir işaretçi gibi mevcut fonksiyonla ilgili bilgileri ve herhangi bir yerel değişkenleri saklayan, call yığını adında bir yığına sahiptir. İşlevler, diğer işlevleri çağırıp ardından geri döndüğünden, yığın, işlevden gelen bilgileri çağrı yığınının ilerisinde tutmak için büyür ve küçülür. Bir programın gerçekten üzerinde çalışma zamanı kontrolü yok; programlama dili, işletim sistemi ve hatta sistem mimarisi tarafından belirlenir.

    Bir yığın, dinamik ve rasgele olarak tahsis edilen herhangi bir hafıza için kullanılan genel bir terimdir; yani, sıra dışı. Bellek genellikle işletim sistemi tarafından tahsis edilir ve bu tahsisi yapmak için API işlevlerini çağıran uygulama kullanılır. Genellikle işletim sistemi tarafından idare edilen dinamik olarak tahsis edilmiş hafızanın yönetilmesi için gereken oldukça fazla miktarda ek yük vardır.

  • Kapsamı nedir?

    Çağrı yığını, programlama anlamında “kapsam” ile ilgili olmayan düşük seviyeli bir konsepttir. Bazı kodları sökerseniz göreceli işaretçi stilinin yığının bölümlerine referansları görürsünüz, ancak daha yüksek bir dil söz konusu olduğunda, dil kendi kapsam kurallarını uygular. Bununla birlikte, bir yığının önemli bir yönü, bir fonksiyon döndüğünde, bu fonksiyon için yerel olan herhangi bir şeyin istiften derhal kurtarılmasıdır. Bu, programlama dillerinin nasıl çalıştığı göz önüne alındığında çalışmasını beklediğiniz şekilde çalışır. Bir yığın halinde, tanımlanması da zordur. Kapsam, işletim sisteminin maruz kaldığı şeydir, ancak programlama diliniz, muhtemelen uygulamanızda "kapsam" ın ne olduğuna ilişkin kurallarını ekler. İşlemci mimarisi ve işletim sistemi, işlemcinin fiziksel adreslere çevirdiği ve sayfa hataları vb. Olduğu sanal adreslemeyi kullanır. Hangi sayfaların hangi uygulamalara ait olduğunu takip eder. Bununla birlikte, gerçekte asla endişelenmenize gerek yoktur, çünkü programlama dilinizin belleği ayırmak ve serbest bırakmak için kullandığı herhangi bir yöntemi kullanırsanız ve hataları kontrol edersiniz (ayırma/serbest bırakma herhangi bir nedenle başarısız olursa).

  • Her birinin boyutunu ne belirler?

    Yine, dile, derleyiciye, işletim sistemine ve mimariye bağlıdır. Bir yığın genellikle önceden tahsis edilir, çünkü tanımı gereği bitişik hafıza olması gerekir (son paragrafta bunun üzerine daha fazla). Dil derleyici veya işletim sistemi boyutunu belirler. Yığın üzerinde büyük miktarda veri saklamıyorsunuz, bu nedenle istenmeyen sonsuz özyineleme (bu nedenle, "yığın taşması") durumları veya diğer olağandışı programlama kararları dışında, asla tam olarak kullanılmaması gereken büyüklükte olacaktır.

    Bir yığın, dinamik olarak tahsis edilebilen herhangi bir şey için genel bir terimdir. Hangi yöne baktığınıza bağlı olarak, sürekli boyut değiştiriyor. Modern işlemcilerde ve işletim sistemlerinde tam olarak nasıl çalıştığı çok soyutlanmıştır, bu nedenle normalde nasıl çalıştığı konusunda endişelenmenize gerek yoktur, bunun dışında (size izin verdiği dillerde) bellek kullanmamalısınız Henüz tahsis etmediniz veya boşalttığınız hafızayıBirini daha hızlı yapan nedir?.

  • What makes one faster?

    The stack is faster because all free memory is always contiguous. No list needs to be maintained of all the segments of free memory, just a single pointer to the current top of the stack. Compilers usually store this pointer in a special, fast register for this purpose. What's more, subsequent operations on a stack are usually concentrated within very nearby areas of memory, which at a very low level is good for optimization by the processor on-die caches.

1305
thomasrutter

(Bu cevabı, bunun aşağı yukarı çekmiş olduğu başka bir soruya taşıdım.)

Sorunuzun cevabı uygulamaya özeldir ve derleyiciler ve işlemci mimarileri arasında değişebilir. Ancak, burada basitleştirilmiş bir açıklama.

  • Hem yığın hem de yığın, temel işletim sisteminden tahsis edilen bellek alanlarıdır (genellikle talep üzerine fiziksel belleğe eşlenen sanal bellek).
  • Çok iş parçacıklı bir ortamda, her iş parçacığının kendi tamamen bağımsız yığını olacak, ancak yığını paylaşacak. Eşzamanlı erişim öbek üzerinde kontrol edilmelidir ve istif üzerinde mümkün değildir.

Yığın

  • Öbek, kullanılmış ve boş blokların bağlantılı bir listesini içerir. Yığındaki yeni tahsisler (new veya malloc tarafından) serbest bloklardan birinden uygun bir blok oluşturularak gerçekleştirilir. Bu, öbek üzerindeki blokların güncellenmesini gerektirir. Yığındaki bloklar hakkındaki bu meta bilgisi, yığın üzerinde de her blokun hemen önünde küçük bir alanda saklanır.
  • Öbek büyüdükçe, yeni bloklar genellikle düşük adreslerden yüksek adreslere doğru tahsis edilir. Böylece öbek, bellek tahsis edildikçe boyut olarak büyüyen bellek bloklarının yığın olarak düşünebilirsiniz. Eğer yığın bir tahsis için çok küçükse, altta yatan işletim sisteminden daha fazla hafıza alınarak boyut genellikle arttırılabilir.
  • Birçok küçük bloğun tahsis edilmesi ve dağıtılması, yığını, kullanılmış blokların arasına serpiştirilmiş çok sayıda küçük serbest bloğun bulunduğu bir durumda bırakabilir. Büyük blok ayırma isteği başarısız olabilir, çünkü serbest blokların hiçbiri, serbest blokların birleşik boyutu yeterince büyük olsa bile, ayırma isteğini karşılayacak kadar büyük değildir. Buna yığın parçalanma adı verilir.
  • Bir serbest bloğa bitişik olan kullanılmış bir blok yerinden çıkarıldığında, yeni serbest blok, yığının parçalanmasını etkili bir şekilde azaltan daha büyük bir serbest blok oluşturmak için bitişik serbest blok ile birleştirilebilir.

The heap

Yığını

  • Yığın çoğunlukla, stack pointer adlı CPU üzerindeki özel bir register ile yakın bir şekilde çalışır. Başlangıçta yığın işaretçisi, yığının üstüne işaret eder (yığındaki en yüksek adres).
  • İşlemcinin değerlerini yığına itmesi ve yığından geri alması için özel talimatları vardır. Her Push değeri yığın göstergesinin geçerli konumuna kaydeder ve yığın göstergesini azaltır. Bir pop yığın göstergesinin gösterdiği değeri alır ve ardından yığın göstergesini arttırır ( yığına bir değer eklemek, azaldığında yığın göstergesini ve değerinin kaldırılması [ değerini artırır, yığının dibe büyüdüğünü unutmayın). Depolanan ve alınan değerler CPU kayıtlarının değerleridir.
  • Bir işlev çağrıldığında, CPU şu komutları kullanan özel yönergeler kullanır: komut göstergesini, yani yığında çalıştırılan kodun adresi. İşlemci daha sonra, Komut göstergesini çağrılan işlevin adresine ayarlayarak işleve atlar. Daha sonra, fonksiyon geri döndüğünde, eski komut göstericisi yığından fırlar ve fonksiyon çağrının hemen ardından kodda yürütme devam eder.
  • Bir fonksiyon girildiğinde, yığın işaretçisi yerel (otomatik) değişkenler için yığına daha fazla yer ayırmak üzere azaltılır. Fonksiyonun bir yerel 32 bit değişkeni varsa, dört bayt yığında bir yana ayarlanır. İşlev döndüğünde, yığın işaretçisi ayrılmış alanı serbest bırakmak için geri hareket ettirilir.
  • Bir işlevin parametreleri varsa, bunlar işleve çağrılmadan önce yığına itilir. İşlevdeki kod daha sonra bu değerleri bulmak için geçerli yığın işaretçisinden yığında dolaşabilir.
  • Yerleştirme işlevi çağrıları bir cazibe işlevi görür. Her yeni çağrı, işlev parametreleri, yerel adresler için geri dönüş adresi ve alan tahsis eder ve bunlar aktivasyon kayıtları iç içe geçmiş çağrılar için istiflenebilir ve işlevler geri döndüğünde doğru şekilde çözülecektir.
  • Yığın sınırlı bir bellek bloğu olduğundan, çok fazla iç içe geçmiş işlev çağırarak ve/veya yerel değişkenler için çok fazla alan ayırarak yığın taşmasına neden olabilirsiniz. Genellikle yığın için kullanılan bellek alanı, yığının altına (en düşük adres) yazmanın CPU'da bir tuzak veya istisna tetikleyeceği şekilde kurulur. Bu istisnai durum daha sonra çalışma zamanı tarafından yakalanabilir ve bir tür yığın taşması istisnasına dönüştürülebilir.

The stack

Bir yığın yerine öbek üzerinde bir işlev atanabilir mi?

Hayır, işlevler için etkinleştirme kayıtları (yani yerel veya otomatik değişkenler), yalnızca bu değişkenleri saklamak için değil, aynı zamanda iç içe geçmiş işlev çağrılarını takip etmek için kullanılan yığında da tahsis edilir.

Öbek nasıl yönetilir gerçekten çalışma zamanı ortamına kalmış. C, malloc ve C++ ise new kullanır, ancak diğer birçok dilde çöp toplama işlemi vardır.Bununla birlikte, yığın işlemci mimarisine yakından bağlı daha düşük bir özelliktir. Yeterince yer olmadığı zaman öbek büyütmek çok zor değildir, çünkü öbekleri işleyen kütüphane çağrısında uygulanabilir. Bununla birlikte, yığını büyütmek çoğu zaman imkansızdır çünkü yığın taşması yalnızca çok geç olduğunda ortaya çıkar; ve yürütme ipliğinin kapatılması tek uygulanabilir seçenektir.

However, the stack is a more low-level feature closely tied to the processor architecture. Growing the heap when there is not enough space isn't too hard since it can be implemented in the library call that handles the heap. However, growing the stack is often impossible as the stack overflow only is discovered when it is too late; and shutting down the thread of execution is the only viable option.

685
Martin Liversage

Aşağıdaki C # kodunda

public void Method1()
{
    int i = 4;
    int y = 2;
    class1 cls1 = new class1();
}

İşte hafızanın nasıl yönetildiği

Picture of variables on the stack

Yalnızca işlev çağrısı yığına girdiği sürece devam etmesi gereken Local Variables. Öbek, yaşam boyu gerçekten tanımadığımız ancak bir süre dayanmalarını beklediğimiz değişkenler için kullanılır. Çoğu dilde, derleme sırasında bir değişkenin yığında depolanması istendiğinde ne kadar büyük olduğunu bilmemiz kritik önem taşır. 

Nesneler (bunları güncelledikçe boyut olarak değişir) öbek üzerinde dururlar, çünkü oluşturma zamanında ne kadar dayanacaklarını bilmiyoruz. Birçok dilde, artık herhangi bir referansı olmayan nesneleri (cls1 nesnesi gibi) bulmak için yığın toplanır. 

Java'da çoğu nesne doğrudan yığına gider. C/C++ gibi dillerde, işaretçilerle ilgilenmediğinizde yapılar ve sınıflar genellikle yığında kalabilir.

Daha fazla bilgi burada bulunabilir:

Yığın ve yığın bellek tahsisi arasındaki fark «timmurphy.org

ve burada: 

Yığın ve Öbek Üzerinde Nesneler Oluşturma

Bu makale yukarıdaki resmin kaynağıdır: Altı önemli .NET kavramı: Yığın, yığın, değer türleri, başvuru türleri, boks ve kutudan çıkarma - CodeProject

ancak bazı yanlışlıklar içerebileceğini unutmayın. 

379
Snowcrash

Yığın Bir işlev çağırdığınızda, o işlevin argümanları ve bazı diğer ek yükler yığının üstüne yerleştirilir. Bazı bilgiler (örneğin, nereye geri dönüleceği gibi) orada da depolanır .İşlevinizde bir değişken bildirdiğinizde, bu değişken de yığında tahsis edilir. 

Yığını yeniden ayırmak oldukça basittir çünkü ayırdığınız ters sırada her zaman ayırmanız gerekir. İşlevlere girdikçe yığın öğeleri eklenir, siz çıktıklarında karşılık gelen veriler kaldırılır. Bu, çok sayıda başka işlev çağıran (ya da özyinelemeli bir çözüm yaratan) çok sayıda işlev çağırmadığınız sürece, yığının küçük bir bölgesinde kalma eğiliminde olduğunuz anlamına gelir.

Yığın.__ Yığın, oluşturduğunuz verileri koyduğunuz yerin genel adıdır. Programınızın kaç tane uzay gemisi oluşturacağını bilmiyorsanız, her bir uzay gemisi oluşturmak için new (veya malloc veya eşdeğeri) operatörünü kullanmanız olasıdır. Bu tahsis bir süre etrafta kalacak, bu yüzden yarattıklarımızdan farklı bir düzende şeyleri serbest bırakacağız. 

Bu nedenle, yığın çok daha karmaşıktır, çünkü sonunda, kullanılmayan bellek bölgeleri vardır - bunlar bellek parçaları parçalanır. İhtiyacınız olan boyutta boş hafıza bulmak zor bir problemdir. Bu yüzden yığıntan kaçınılması gerekir (yine de sıklıkla kullanılmasına rağmen).

Uygulama Hem yığın hem de yığının uygulanması genellikle çalışma zamanına/işletim sistemine bağlıdır. Genellikle oyunlar ve performans açısından kritik olan diğer uygulamalar, yığından büyük miktarda bellek alan kendi bellek çözümlerini oluşturur ve daha sonra işletim sistemine bellek güvenmekten kaçınmak için dahili olarak tüketir. 

Bu, yalnızca bellek kullanımınızın normdan oldukça farklı olması durumunda pratiktir - yani, devasa bir işlemde bir seviye yüklediğiniz ve tüm devri başka bir büyük işlemde başarabileceğiniz oyunlar için.

Bellekteki fiziksel konum.__ Bu, Sanal Bellek adlı bir teknoloji nedeniyle düşündüğünüzden daha az ilgilidir ve bu, programınızın fiziksel verilerin bir yerde olduğu belirli bir adrese erişiminiz olduğunu düşünmesini sağlar başka (sabit diskte bile!). Arama ağacınız derinleştikçe, yığın için aldığınız adresler artan sıradadır. Yığın için adresler tahmin edilemez (yani belirli bir uygulama şeklinde) ve açıkçası önemli değil.

194
Tom Leys

Açıklığa kavuşturmak için, bu cevabı yanlış bilgi içeriyor ( thomas yorumlardan sonra cevabını düzeltti, harika :)). Diğer cevaplar sadece statik tahsisatın ne demek olduğunu açıklamaktan kaçınır. Bu yüzden, üç ana tahsisat şeklini ve bunların genellikle aşağıdaki yığın, yığın ve veri segmenti ile olan ilişkilerini açıklayacağım. İnsanların anlamalarına yardımcı olmak için hem C/C++ hem de Python'da bazı örnekler göstereceğim.

"Statik" (AKA statik olarak tahsis edilmiştir) değişkenleri yığında tahsis edilmemiştir. Bunu varsaymayın - birçok insan sadece “statik” “yığın” gibi ses çıkardığı için yapar. Aslında ne yığında ne de yığında varlar. veri segmenti olarak adlandırılanın bir parçasıdır.

Ancak, genellikle "yığın" ve "yığın" yerine "kapsam" ve "lifetime" göz önünde bulundurulması daha iyidir.

Kapsam, kodun hangi bölümlerinin bir değişkene erişebileceği anlamına gelir. Genel olarak global kapsam (sadece mevcut fonksiyonla erişilebilir) ve global kapsam (herhangi bir yerden erişilebilir), kapsam çok daha karmaşık olabilse de düşünürüz.

Ömür boyu, program yürütme sırasında bir değişkenin tahsis edildiği ve çıkarıldığı zaman anlamına gelir. Genellikle statik ayırma (değişken programın tüm süresi boyunca devam eder, aynı bilgiyi birkaç işlev çağrısında saklamak için faydalı kılar) düşünürsek, otomatik ayırma (değişken sadece bir arama sırasında devam eder) bir işleve, yalnızca işleviniz sırasında kullanılan ve işiniz bittikten sonra atılabilen bilgilerin saklanması için kullanışlı hale getirilmesi, dinamik ayırma (süresi çalışma zamanında tanımlanmış değişkenler, statik veya otomatik gibi derleme zamanı yerine) ).

Her ne kadar çoğu derleyici ve yorumlayıcı bu davranışı istif, yığın vb. Kullanmaya benzer şekilde uygulasa da, bir derleyici bazen davranışların doğru olması isteniyorsa bu kuralları bozabilir. Örneğin, optimizasyon nedeniyle bir yerel değişken yalnızca bir kayıt defterinde bulunabilir veya çoğu yerel değişken yığında bulunsa bile tamamen kaldırılabilir. Birkaç yorumda belirtildiği gibi, bir yığın veya bir yığın bile kullanmayan bir derleyici kullanmakta serbestsiniz, bunun yerine bazı diğer depolama mekanizmalarını kullanmakta özgürsünüz (nadiren yapılır, çünkü yığınlar ve yığınlar bunun için harikadır).

Bunları açıklamak için bazı basit açıklamalı C kodları vereceğim. Öğrenmenin en iyi yolu, bir programı hata ayıklayıcı altında çalıştırmak ve davranışı izlemektir. Python okumayı tercih ediyorsanız, cevabın sonuna atlayın :)

// Statically allocated in the data segment when the program/DLL is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in the code
int someGlobalVariable;

// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in this particular code file
static int someStaticVariable;

// "someArgument" is allocated on the stack each time MyFunction is called
// "someArgument" is deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
void MyFunction(int someArgument) {

    // Statically allocated in the data segment when the program is first loaded
    // Deallocated when the program/DLL exits
    // scope - can be accessed only within MyFunction()
    static int someLocalStaticVariable;

    // Allocated on the stack each time MyFunction is called
    // Deallocated when MyFunction returns
    // scope - can be accessed only within MyFunction()
    int someLocalVariable;

    // A *pointer* is allocated on the stack each time MyFunction is called
    // This pointer is deallocated when MyFunction returns
    // scope - the pointer can be accessed only within MyFunction()
    int* someDynamicVariable;

    // This line causes space for an integer to be allocated in the heap
    // when this line is executed. Note this is not at the beginning of
    // the call to MyFunction(), like the automatic variables
    // scope - only code within MyFunction() can access this space
    // *through this particular variable*.
    // However, if you pass the address somewhere else, that code
    // can access it too
    someDynamicVariable = new int;


    // This line deallocates the space for the integer in the heap.
    // If we did not write it, the memory would be "leaked".
    // Note a fundamental difference between the stack and heap
    // the heap must be managed. The stack is managed for us.
    delete someDynamicVariable;

    // In other cases, instead of deallocating this heap space you
    // might store the address somewhere more permanent to use later.
    // Some languages even take care of deallocation for you... but
    // always it needs to be taken care of at runtime by some mechanism.

    // When the function returns, someArgument, someLocalVariable
    // and the pointer someDynamicVariable are deallocated.
    // The space pointed to by someDynamicVariable was already
    // deallocated prior to returning.
    return;
}

// Note that someGlobalVariable, someStaticVariable and
// someLocalStaticVariable continue to exist, and are not
// deallocated until the program exits.

Ömür boyu ve kapsamı arasında ayrım yapmanın neden önemli olduğuna dair belirgin bir örnek, bir değişkenin yerel kapsamı olabilir, ancak statik ömre sahip olabilir - örneğin, yukarıdaki kod örneğinde "someLocalStaticVariable". Bu tür değişkenler ortak ancak resmi olmayan adlandırma alışkanlıklarımızı kafa karıştırıcı hale getirebilir. Örneğin, "yerel" derken genellikle "yerel olarak otomatik olarak atanmış değişken" anlamına gelir ve genel derken genellikle "genel olarak statik olarak atanmış değişken" anlamına geliriz. Ne yazık ki "dosya statik olarak tahsis edilmiş değişkenleri kapsamalı" gibi şeyler söz konusu olduğunda pek çok insan sadece ... "huh ???" diyor.

C/C++ 'daki bazı sözdizimi seçimleri bu sorunu daha da arttırmaktadır - örneğin, birçok kişi global değişkenlerin aşağıda gösterilen sözdizimi nedeniyle "statik" olmadığını düşünmektedir.

int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation

int main() {return 0;}

Yukarıdaki bildirime "statik" anahtar kelimesini koymak, var2'nin global kapsam içermediğini engellediğine dikkat edin. Bununla birlikte, global var1 statik tahsise sahiptir. Bu sezgisel değil! Bu nedenle, kapsam açıklanırken "statik" kelimesini asla kullanmaya çalışmam ve bunun yerine "dosya" veya "dosya sınırlı" kapsamı gibi bir şey demeye çalışıyorum. Ancak birçok kişi, yalnızca bir kod dosyasından erişilebilen bir değişkeni tanımlamak için "statik" veya "statik kapsam" ifadesini kullanır. Ömür boyu bağlamında, "statik" her zaman, değişkenin program başlangıcında tahsis edildiği ve program çıktığında devre dışı bırakıldığı anlamına gelir.

Bazı insanlar bu kavramları C/C++ 'ya özgü olarak düşünür. Onlar değil. Örneğin, aşağıdaki Python örneği, üç tahsis türünün hepsini göstermektedir (yorumlanmış dillerde buraya girmeyeceğim bazı ince farklılıklar olabilir).

from datetime import datetime

class Animal:
    _FavoriteFood = 'Undefined' # _FavoriteFood is statically allocated

    def PetAnimal(self):
        curTime = datetime.time(datetime.now()) # curTime is automatically allocatedion
        print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)

class Cat(Animal):
    _FavoriteFood = 'tuna' # Note since we override, Cat class has its own statically allocated _FavoriteFood variable, different from Animal's

class Dog(Animal):
    _FavoriteFood = 'steak' # Likewise, the Dog class gets its own static variable. Important to note - this one static variable is shared among all instances of Dog, hence it is not dynamic!


if __== "__main__":
    whiskers = Cat() # Dynamically allocated
    fido = Dog() # Dynamically allocated
    rinTinTin = Dog() # Dynamically allocated

    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

    Dog._FavoriteFood = 'milkbones'
    whiskers.PetAnimal()
    fido.PetAnimal()
    rinTinTin.PetAnimal()

# Output is:
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is milkbones
# Thank you for petting me. But it's 13:05:02.256000, you should feed me. My favorite food is milkbones
174
davec

Diğerleri geniş vuruşlara oldukça iyi cevap verdiler, bu yüzden birkaç detay vereceğim.

  1. Yığın ve yığının tekil olması gerekmez. Birden fazla yığının olduğu ortak bir durum, bir işlemde birden fazla iş parçacığınızın bulunmasıdır. Bu durumda, her iş parçacığının kendi yığını vardır. Birden fazla öbeğe de sahip olabilirsiniz, örneğin, bazı DLL yapılandırmaları farklı yığınlardan farklı DLL'lerin ayrılmasına neden olabilir, bu yüzden farklı bir kütüphane tarafından ayrılan belleği serbest bırakmak genellikle kötü bir fikirdir.

  2. C'de yığında tahsis eden alloca kullanarak, yığında tahsis edilen tahsise karşılık değişken uzunluk tahsisinin avantajlarından yararlanabilirsiniz. Bu bellek return ifadenizden kurtulmaz, ancak bir çizik tamponu için kullanışlıdır.

  3. Windows'ta fazla kullanmadığınız büyük bir geçici arabellek yapmak ücretsiz değildir. Bunun nedeni, derleyicinin, yığının var olduğundan emin olmak için işlevinize her girdiğinizde çağrılan bir yığın prob döngüsü üretmesidir (çünkü Windows, yığının ne zaman büyümesi gerektiğini algılamak için yığınızın sonunda tek bir koruma sayfası kullanır. Belleğe yığının ucundan birden fazla sayfa erişirseniz kilitleneceksiniz). Örnek:

void myfunction()
{
   char big[10000000];
   // Do something that only uses for first 1K of big 99% of the time.
}
158
Don Neufeld

Diğerleri doğrudan sorunuzu cevapladı, ancak yığını ve öbekleri anlamaya çalışırken, geleneksel bir UNIX işleminin bellek düzenini göz önünde bulundurmanın yararlı olduğunu düşünüyorum (konu ve mmap() tabanlı ayırıcılar olmadan). Bellek Yönetimi Sözlüğü web sayfası bu bellek düzeninin bir şemasına sahiptir.

Yığın ve öbek, geleneksel olarak işlemin sanal adres alanının karşıt uçlarına yerleştirilir. Yığına erişildiğinde, çekirdek tarafından ayarlanan bir boyuta (setrlimit(RLIMIT_STACK, ...) ile ayarlanabilir) kadar otomatik büyür. Bellek ayırıcısı, brk() veya sbrk() sistem çağrısını çağırdığında, işlemin sanal adres alanına daha fazla fiziksel bellek sayfası eşleştirildiğinde yığın büyür. 

Bazı gömülü sistemler gibi sanal belleği olmayan sistemlerde, aynı temel düzen genellikle yığın ve yığının boyutunda sabitlenmesi dışında uygulanır. Bununla birlikte, diğer gömülü sistemlerde (Microchip PIC mikro denetleyicilerini temel alan sistemler gibi), program yığını, veri hareketi yönergeleri tarafından adreslenemeyen ayrı bir bellek bloğudur ve yalnızca program akış yönergeleriyle dolaylı olarak değiştirilebilir veya okunabilir (çağrı, geri dönüş, vb.) Intel Itanium işlemciler gibi diğer mimarilerde çoklu yığınlar var . Bu anlamda, yığın CPU mimarisinin bir elemanıdır.

127
bk1e

Yığın, 'pop' (yığından bir değer çıkarın ve döndürün) ve 'Push' (Yığın'a bir değer itin) gibi birkaç anahtar Assembly dili yönergesiyle işlenebilen bir bellek parçasıdır; Bir alt yordam çağrısı - bu, yığına geri dönmek için adresi iter) ve geri dönmek (bir alt yordamdan geri dönmek - bu, adresi yığından çıkar ve ona atlar). İstenilen şekilde ayarlanabilen yığın göstergesinin altındaki bellek bölgesidir. Yığın, argümanları alt yordamlara aktarmak ve ayrıca alt yordamları çağırmadan önce kayıtlardaki değerleri korumak için de kullanılır.

Öbek, işletim sistemi tarafından bir uygulamaya, tipik olarak malloc benzeri bir sistem aracılığıyla verilen belleğin bir kısmıdır. Modern işletim sistemlerinde bu bellek yalnızca arama işleminin erişebildiği bir sayfalar kümesidir.

Yığının boyutu çalışma zamanında belirlenir ve genellikle program başladıktan sonra büyümez. Bir C programında, istifin her fonksiyonda bildirilen her değişkeni tutacak kadar büyük olması gerekir. Yığın gerektiğinde dinamik bir şekilde büyüyecek, ancak işletim sistemi nihayetinde çağrı yapıyor (mal yığınının istediği değerden daha fazla yığın büyütecek, böylece en azından bazı gelecekteki mallocların çekirdeğe geri dönmesi gerekmeyecek Daha fazla hafıza kazanın.Bu davranış genellikle özelleştirilebilir)

Programı başlatmadan önce yığını tahsis ettiğiniz için, yığını kullanmadan önce malloc'la uğraşmanıza gerek kalmaz, bu yüzden orada küçük bir avantaj. Uygulamada sanal bellek alt sistemlerine sahip modern işletim sistemlerinde neyin hızlı ve neyin yavaş olacağını tahmin etmek çok zordur, çünkü sayfaların nasıl uygulandığı ve nerede depolandıkları bir uygulama detayıdır. 

108
Daniel Papasian

Bence bu konuda birçok başka insan size doğru cevaplar verdi.

Ancak kaçırılan bir detay, "yığın" ın aslında "serbest mağaza" olarak adlandırılması gerektiğidir. Bu ayrımın nedeni, orijinal serbest mağazanın "binom yığını" olarak bilinen bir veri yapısı ile gerçekleştirilmiş olmasıdır. Bu nedenle, malloc ()/free () 'nin erken uygulamalarından tahsis bir yığıntan tahsis edildi. Ancak, bu modern günde, çoğu ücretsiz mağaza binom yığınları olmayan çok ayrıntılı veri yapılarıyla uygulanmaktadır.

107
Heath

Bir yığın nedir?

Bir yığın, tipik olarak özenle düzenlenmiş bir nesne yığınıdır.

 Enter image description here

Bilgi işlem mimarilerindeki yığınlar, verilerin ilk giren ilk çıkar yöntemiyle eklendiği veya çıkarıldığı bellek bölgeleridir. 
Çok iş parçacıklı bir uygulamada, her iş parçacığının kendi yığını olacaktır.

Bir yığın nedir?

Bir yığın, başıboş bir şekilde biriktirilmiş olan düzensiz şeyler topluluğudur.

 Enter image description here

Bilgi işlem mimarilerinde yığın, işletim sistemi veya bellek yöneticisi kütüphanesi tarafından otomatik olarak yönetilen dinamik olarak ayrılmış bir bellek alanıdır. 
Öbek üzerindeki bellek program yürütülürken düzenli olarak tahsis edilir, tahsis edilir ve yeniden boyutlandırılır ve bu parçalanma olarak adlandırılan bir soruna yol açabilir. 
Parçalanma, bellek nesnelerine aralarında ilave bellek nesneleri tutmak için çok küçük olan küçük boşluklar tahsis edildiğinde meydana gelir. 
Net sonuç, daha fazla bellek ayırması için kullanılamayan yığın alanının bir yüzdesidir.

İkisi birlikte

Çok iş parçacıklı bir uygulamada, her iş parçacığının kendi yığını olacaktır. Ancak, tüm farklı iş parçacıkları yığını paylaşacak. 
Farklı iş parçacığı çok parçacıklı bir uygulamada yığını paylaştığı için, bu aynı zamanda, iş parçacığı içindeki aynı bellek parçalarına erişmeye ve bunları manipüle etmeye çalışmadıkları için dişler arasında bir miktar koordinasyon olması gerektiği anlamına gelir. Aynı zaman.

Hangisi daha hızlı - yığın mı, yığın mı? Ve neden?

Yığın yığından çok daha hızlı. 
Bunun nedeni hafızanın yığına tahsis edilme biçimidir. 
Yığına bellek tahsis etmek, yığın işaretçisini yukarı hareket ettirmek kadar kolaydır.

Programlamaya yeni başlayanlar için, yığını kullanmak, muhtemelen daha kolay olduğu için iyi bir fikirdir. 
Yığınının küçük olması nedeniyle, verileriniz için tam olarak ne kadar hafızaya ihtiyaç duyacağınızı ya da verilerinizin boyutunun çok küçük olduğunu bilmeniz durumunda kullanmak istersiniz. 
Verileriniz için çok fazla belleğe ihtiyaç duyacağınızı ya da ne kadar belleğe ihtiyaç duyacağınızdan emin değilsiniz (dinamik bir dizide olduğu gibi).

Java Bellek Modeli

 Enter image description here

Yığın, yerel değişkenlerin (yöntem parametreleri dahil) depolandığı bellek alanıdır. Nesne değişkenleri söz konusu olduğunda, bunlar yalnızca öbek üzerindeki gerçek nesnelere referanslar (işaretçiler).
Bir nesnenin her başlatılışında, o nesnenin verilerini (durumunu) tutmak için bir yığın yığın bellek bir kenara konulur. Nesneler başka nesneler içerebildiğinden, bu verilerin bazıları aslında iç içe geçmiş nesnelere referanslar içerebilir.

101
Shreyos Adikari

Yığınla ilginç şeyler yapabilirsiniz. Örneğin, alloca (kullanımıyla ilgili çok fazla uyarının üstesinden gelebileceğinizi varsayarsak) gibi fonksiyonlara sahipsiniz, ki bu, yığın için değil yığın için özellikle yığını kullanan bir malloc şeklidir.

Bununla birlikte, yığın tabanlı bellek hataları, yaşadığım en kötü hatalardan bazıları. Yığın bellek kullanıyorsanız ve ayrılan bloğunuzun sınırlarını aştıysanız, bir segment hatasını tetikleme şansınız oldukça yüksektir. (% 100 değil: bloğunuz tesadüfen önceden tahsis ettiğiniz bir başkasına bitişik olabilir.) Ancak yığınta yaratılan değişkenler her zaman birbiriyle bitişik olduğundan, sınırların dışına yazılması başka bir değişkenin değerini değiştirebilir. Programımın mantık yasalarına uymayı bıraktığını hissettiğimde muhtemelen taşma olduğunu öğrendim.

87
Peter

Basitçe, yığın yerel değişkenlerin yaratıldığı yerdir. Ayrıca, program sayacını bir alt programa her çağırdığınızda (bir sonraki makinenin talimatına işaretçi) ve tüm önemli kayıtlar ve bazen parametreler yığına itilir. Ardından, alt rutin içindeki herhangi bir yerel değişken yığının üzerine itilir (ve oradan kullanılır). Alt yordam bittiğinde, tüm bunlar yığından geri atılır. PC ve kayıt verileri, alıp geldiği yere geri koyulur, böylece programınız mutlu bir şekilde devam eder.

Öbek, bellek dinamik bellek tahsislerinden oluşur (açık "yeni" veya "tahsis" çağrıları). Farklı boyutlardaki hafıza bloklarını ve tahsisat durumlarını takip edebilen özel bir veri yapısıdır.

"Klasik" sistemlerde RAM, yığın işaretçisi belleğin dibinde, yığın işaretçisi en üstte başladı ve birbirlerine doğru büyüdüler. Çakışırlarsa, RAM'iniz biter. Yine de, modern çoklu iş parçacıklı işletim sistemlerinde çalışmaz. Her iş parçacığının kendi yığınına sahip olması gerekir ve bunlar dinamik olarak oluşturulabilir.

84
T.E.D.

WikiAnwser'dan.

Yığın

Bir işlev veya yöntem, sırayla başka bir işlevi vb. Çağıran başka bir işlevi çağırdığında, tüm bu işlevlerin yürütülmesi, en son işlevin değerini döndürene kadar askıya alınır.

Bu askıya alınmış işlev çağrıları zinciri, yığın işlevidir, çünkü yığındaki öğeler (işlev çağrıları) birbirine bağlıdır.

İstisna işleme ve iplik yürütme işlemlerinde dikkate alınması gereken yığın önemlidir.

Yığın

Yığın basitçe değişkenlerin depolanması için programlar tarafından kullanılan hafızadır .. ... Yığın elemanının (değişkenler) birbiriyle hiçbir bağımlılığı yoktur ve her zaman her zaman rastgele erişilebilir.

78
devXen

Yığın

  • Çok hızlı erişim
  • Değişkenlerin açıkça ayrılması gerekmez
  • Alan CPU tarafından verimli bir şekilde yönetilir, bellek parçalanmaz
  • Sadece yerel değişkenler
  • Yığın boyutunda sınır (işletim sistemine bağlı)
  • Değişkenler yeniden boyutlandırılamaz

Yığın

  • Değişkenlere global olarak erişilebilir
  • Bellek boyutunda limit yok
  • (Nispeten) daha yavaş erişim
  • Alanın garantili ve verimli kullanılmaması, hafıza blokları tahsis edildikten sonra hafıza zaman içinde parçalanabilir,
  • Belleği yönetmelisiniz (değişkenleri tahsis etmekten ve serbest bırakmaktan sorumlusunuz)
  • Değişkenler realloc () kullanılarak yeniden boyutlandırılabilir
50
unknown

Tamam, basitçe ve kısa bir deyişle, sıralı ve sıralı değil ... demek!

Yığın: Yığın maddelerde, işler üst üste gelir, işlenmeleri daha hızlı ve daha verimli olur! ... 

Böylece, her zaman belirli bir öğeye işaret edecek bir endeks vardır, işlem daha hızlı olacaktır, öğeler arasında da bir ilişki vardır! ...

Heap: Sipariş yok, işlem daha yavaş olacak ve değerler belirli bir sipariş veya indeks olmadan birbirine karışmış durumda ... rastgele ve aralarında bir ilişki yok. ..

Nasıl göründüklerini göstermek için aşağıdaki resmi de oluşturuyorum:

 enter image description here

38
Alireza

Kısacası

Her ikisi de bilgisayarın RAM'inde depolanan statik bellek tahsisi için bir yığın ve dinamik bellek tahsisi için bir yığın kullanılır.


Detayda

Yığın

Yığın, CPU tarafından oldukça yakından yönetilen ve optimize edilen "LIFO" (ilk giren ilk çıkar) veri yapısıdır. Bir işlev her yeni bir değişken bildirdiğinde, yığına "itilir". Sonra bir işlev her çıktığında, o işleve yığının üstüne itilen tüm değişkenler serbest bırakılır (yani silinirler). Bir yığın değişkeni serbest bırakıldığında, bu bellek bölgesi diğer yığın değişkenleri için kullanılabilir duruma gelir.

Yığını değişkenleri saklamak için kullanmanın avantajı, belleğin sizin için yönetilmesidir. Belleği elle ayırmanız veya bir daha ihtiyaç duymadığınızda bir kez serbest bırakmanız gerekmez. Dahası, CPU yığın belleği çok verimli bir şekilde organize ettiğinden, yığın değişkenlerinden okuma ve yazma çok hızlıdır.

Daha fazla bulabilirsiniz burada.


Yığın

Öbek, bilgisayarınızın belleğinin sizin için otomatik olarak yönetilmeyen ve CPU tarafından sıkı şekilde yönetilmeyen bir bölgesidir. Daha serbest yüzen bir bellek bölgesidir (ve daha büyüktür). Öbek üzerinde bellek tahsis etmek için, yerleşik C işlevlerine sahip olan malloc () veya calloc () kullanmanız gerekir. Öbek üzerinde bellek tahsis ettikten sonra, artık gerekmediğinde bu belleği çıkarmak için free () kullanmaktan sorumlusunuz.

Bunu yapmazsanız, programınız bellek sızıntısı olarak bilinen şeye sahip olacaktır. Yani, öbek üzerindeki bellek hala bir kenara bırakılacak (ve diğer işlemler için geçerli olmayacak). Hata ayıklama bölümünde göreceğimiz gibi, bellek sızıntılarını tespit etmenize yardımcı olacak Valgrind adında bir araç var.

Yığının aksine, öbek değişken boyutta boyut sınırlamalarına sahip değildir (bilgisayarınızın belirgin fiziksel sınırlamaları dışında). Yığın hafızasından okunması ve yazılması biraz daha yavaştır, çünkü birinin yığın hafızasına erişmek için işaretçiler kullanması gerekir. İşaretçiler hakkında kısaca konuşacağız.

Yığının aksine, öbek üzerinde yaratılan değişkenlere, programınızın herhangi bir yerinde, herhangi bir işlev tarafından erişilebilir. Yığın değişkenleri aslında kapsamda globaldir.

Daha fazla bulabilirsiniz burada.


Yığında tahsis edilen değişkenler doğrudan belleğe kaydedilir ve bu belleğe erişim çok hızlıdır ve tahsisi program derlendiğinde ele alınır. Bir işlev veya yöntem, sırayla başka bir işlevi vb. Çağıran başka bir işlevi çağırdığında, tüm bu işlevlerin yürütülmesi, en son işlevin değerini döndürene kadar askıya alınır. Yığın her zaman LIFO sırasına ayrılır, en son ayrılan blok her zaman serbest bırakılacak bir sonraki bloktur. Bu, yığını takip etmeyi gerçekten kolaylaştırır, bir bloğu yığından serbest bırakmak, bir işaretçiyi ayarlamaktan başka bir şey değildir.

Öbek üzerinde tahsis edilen değişkenler çalışma zamanında tahsis edilmiş belleklerine sahiptir ve bu belleğe erişim biraz daha yavaştır, ancak öbek boyutu yalnızca sanal belleğin boyutu ile sınırlıdır. Yığın öğelerinin birbirleriyle hiçbir bağımlılığı yoktur ve her zaman herhangi bir zamanda rastgele erişilebilir. Bir bloğu istediğiniz zaman tahsis edebilir ve istediğiniz zaman boşaltabilirsiniz. Bu, herhangi bir zamanda yığının hangi bölümlerinin tahsis edildiğini veya serbest bırakıldığını takip etmeyi çok daha karmaşık hale getirir.

 Enter image description here

Derleme süresinden önce ne kadar veri ayırmanız gerektiğini tam olarak biliyorsanız yığını kullanabilirsiniz. Çok büyük değil. Çalışma zamanında tam olarak ne kadar veriye ihtiyaç duyacağınızı bilmiyorsanız veya çok fazla veri ayırmanız gerekirse, yığını kullanabilirsiniz.

Çok iş parçacıklı bir durumda, her iş parçacığı kendi tamamen bağımsız yığına sahip olacak, ancak yığını paylaşacaklar. Yığın iş parçacığına özgü ve yığın uygulamaya özgüdür. İstisna işleme ve iplik yürütme işlemlerinde dikkate alınması gereken yığın önemlidir.

Her iş parçacığı bir yığın alır, ancak uygulama için genellikle yalnızca bir yığın vardır (farklı ayırma türleri için birden fazla yığın olması nadir değildir).

 Enter image description here

Çalışma zamanında, uygulama daha fazla yığın gerektiriyorsa, boş bellekten bellek ayırabilir ve yığın belleğe ihtiyaç duyuyorsa, uygulama için boş bellekten ayrılmış bellek belleği ayırabilir.

Hatta daha fazla ayrıntı verildi burada ve burada .


Şimdi, sorunuza cevap verin [].

İşletim sistemi veya dil çalışma zamanı ne ölçüde kontrol ediliyor?

İşletim sistemi, iş parçacığı oluşturulduğunda her sistem düzeyinde iş parçacığı için yığını ayırır. Genellikle işletim sistemi, öbek için uygulama ayırmak için dil çalışma zamanı tarafından çağrılır.

Daha fazla bulabilirsiniz burada.

Kapsamları nedir?

Zaten üstte verildi.

"Derleme süresinden önce ne kadar veri ayırmanız gerektiğini tam olarak biliyorsanız yığını kullanabilirsiniz, çok büyük değil. Eğer çalışma zamanında tam olarak ne kadar veriye ihtiyacınız olacağını bilmiyorsanız yığını kullanabilirsiniz. Çok fazla veri ayırmanız gerekiyor. "

Daha fazlası here içinde bulunabilir.Her birinin boyutunu ne belirler?.

Hangisini daha hızlı yapan nedir?.

Ayrıca yığın-yığın yığını sadece bir performans değerlendirmesi değildir; Aynı zamanda nesnelerin beklenen ömrü hakkında size çok şey anlatır.

Ayrıntılar here 'dan bulunabilir.

Also, stack vs. heap is not only a performance consideration; it also tells you a lot about the expected lifetime of objects.

Details can be found from here.

35
Abrar Jahin

1980'lerde UNIX, büyük şirketlerle kendi şirketlerini kurmakta olan tavşanlara benzer şekilde yayıldı .. __ Exxon'un tarihe kaybedilen onlarca marka ismi vardı.

Tipik bir C programı, br. () değerini değiştirerek arttırma şansı olan bir haftanın hafızasına kondu. yığın.

Tek STACK, tipik olarak, bir sonraki sabit bellek bloğunun tepesine kadar değerli hiçbir şey içermeyen bir bellek yolu olan, HEAP'ın altındaki bir alandır dönemin ünlü hacklerinden birinde.

Tipik bir hafıza bloğu, BSS (sıfır değer bloğu) idi. O, bir üreticinin teklifinde kazara sıfırlanmadı. (Çalışma zamanı), ana işlevler ve kütüphaneler.

UNIX’te sanal belleğin ortaya çıkması birçok kısıtlamayı değiştirir .. UNIX bu kısıtlamalardan muzdarip olmayan bir Multics idi .. __ İşte dönemin hafıza düzenlerinden birini gösteren şematik.

A typical 1980s style UNIX C program memory layout

35
jlettvin

stack, yığın ve her işlemin data sanal belleğindeki:

 stack, heap and static data

29
Yousha Aleayoub

Birkaç sent: Sanırım, hafızayı grafiksel ve basit hale getirmek iyi olacak:

 This is my vision of process memory construction with simplification for more easy understanding wht happening


Oklar - Yığın ve yığının nerede büyüdüğünü, işlem yığın büyüklüğünün OS'de tanımlanan, yığın yığın büyüklüğü sınırlarının iş parçacığındaki parametrelere göre genellikle API oluşturduğunu gösterir. Yığın genellikle işlem maksimum sanal bellek boyutuyla sınırlanır, örneğin 32 bit 2-4 GB.

Çok basit bir yol: işlem yığını, işlem için ve içindeki tüm iş parçacığı için geneldir, malloc () gibi bir şey ile ortak durumda bellek ayırma için kullanılır.

Yığın, genel durum işlevi geri dönüş işaretçilerinde ve değişkenlerde, işlev çağrısında parametre olarak işlenen yerel işlev değişkenlerinde saklamak için hızlı bellektir.

24
Maxim Akristiniy

Bazı cevaplar nitpicking gittiği için, akarıma katkıda bulunacağım.

Şaşırtıcı bir şekilde, hiç kimse birden fazla (yani çalışan işletim sistemi düzeyinde çalışan iş parçacıklarının sayısıyla ilgili değil) çağrı yığınlarının yalnızca egzotik dillerde (PostScript) veya platformlarda (Intel Itanium) değil, aynı zamanda fiber , green thread ve eşyordamlar .

Lifler, yeşil iplikler ve koroinler benzer şekilde, bu da kafa karışıklığına neden olur. Lifler ve yeşil iplikler arasındaki fark, eskiden kooperatif çoklu görev kullanmasıdır, ikincisi ise kooperatif veya önleyici olanı (veya her ikisini de) içerebilir. Lifler ve koroinler arasındaki fark için, bakınız burada .

Her durumda, hem liflerin, hem yeşil ipliklerin hem de coroutinlerin amacı eşzamanlı olarak çalışan çoklu fonksiyonlara sahip olmakla birlikte, değil paralel olarak (bakınız bu SO sor ayrım için) tek bir işletim sistemi düzeyinde iş parçacığında, kontrolü birbirinden ileri ve geri organize bir şekilde aktarmak.

Fiberleri, yeşil iplikleri veya coroutinleri kullanırken, genellikle işlev başına ayrı bir yığına sahip olursunuz. (Teknik olarak, yalnızca bir yığın değil tüm yürütme bağlamı işlev başınadır. En önemlisi, CPU kaydeder.) Her iş parçacığı için, aynı anda çalışan işlevlerin olduğu kadar çok yığın vardır ve iş parçacığı her işlevin yürütülmesi arasında geçiş yapar programınızın mantığına göre. Bir işlev sona erdiğinde, yığını yok edilir. Yani, yığınların sayısı ve ömürleri dinamiktir ve OS düzeyinde iş parçacıklarının sayısına göre belirlenmez!

" genellikle işlev başına ayrı bir yığına sahip" dediğimi unutmayın. Her ikisi de stackful ve stackless Koroutinler uygulamaları vardır. En göze çarpan yığın C++ uygulamaları Boost.Coroutine ve Microsoft PPL 's async/await. (Bununla birlikte, C++ 17'ye önerilen C++ 'nın yeniden başlatılabilir işlevler (a.k.a. "async ve await") yığınsız koroinler kullanması muhtemeldir.)

Lifler, C++ standart kütüphanesine öneridir. Ayrıca, bazı üçüncü taraflar var kütüphaneler . Yeşil iplikler Python ve Ruby gibi dillerde oldukça popülerdir.

21
shakurov

Önemli noktalar zaten kapsanmış olsa da paylaşacak bir şeyim var.

Yığın  

  • Çok hızlı erişim.
  • RAM'de saklanır.
  • İşlev çağrıları buraya yerel değişkenler ve iletilen işlev parametreleriyle birlikte yüklenir.
  • Program kapsam dışı kaldığında alan otomatik olarak serbest bırakılır.
  • Sıralı hafızaya kaydedilir.

Yığın

  • Stack ile karşılaştırmalı olarak yavaş erişim.
  • RAM'de saklanır.
  • Dinamik olarak oluşturulmuş değişkenler burada saklanır, bu kullanımdan sonra daha sonra ayrılan hafızanın boşaltılmasını gerektirir.
  • Hafıza tahsisinin yapıldığı her yerde, işaretçi tarafından her zaman erişilebilir.

İlginç not:

  • İşlev çağrıları yığın halinde saklansaydı, 2 dağınık noktaya yol açardı:
    1. Yığındaki sıralı depolama nedeniyle yürütme daha hızlıdır. Yığın içinde depolama, çok fazla zaman harcamasına ve böylece tüm programın daha yavaş çalışmasına neden olur.
    2. İşlevler öbek içinde saklanırsa (işaretçi tarafından gösterilen karışık depolama), arayan adrese geri dönmenin (hafızada sıralı saklama nedeniyle ortaya çıkan yığın) geri dönüşü olmazdı.
12

Bir çok cevap kavram olarak doğrudur, ancak alt programların çağrılmasına izin vermek için donanım tarafından (yani mikroişlemci) bir yığına ihtiyaç duyulduğunu not etmeliyiz. (OOP adamları bunu arayacak yöntemler)

Yığında iade adreslerini kaydeder ve → Push/ret → pop komutunu doğrudan donanımdan yönetirsiniz.

Parametreleri iletmek için yığını kullanabilirsiniz .. yazmaç kullanmaktan daha yavaş olsa bile (bir mikroişlemci gurusu ya da iyi bir 1980'lerin BIOS kitabı…)

  • Yığın olmadan hayır mikroişlemci çalışabilir. (Assembly dilinde bile alt rutin/fonksiyonlar olmadan bir program düşünemiyoruz)
  • Öbek olmadan yapabilirsiniz. (Bir Assembly dili programı, yığın bir işletim sistemi konsepti, malloc olarak bir işletim sistemi/lib çağrısı olduğu için olmadan da çalışabilir.

Yığın kullanımı şu şekilde daha hızlı:

  • Donanım ve hatta Push/pop çok verimlidir.
  • malloc, çekirdek moduna girmeyi gerektirir, bazı kodları yürütmek için kilit/semafor (veya diğer senkronizasyon ilkellerini) kullanın ve tahsisi takip etmek için gereken bazı yapıları yönetin.
8
ingconti

Vaov! Pek çok cevap ve onlardan birinin doğru anladığını sanmıyorum ...

1) Nerede ve ne (fiziksel olarak gerçek bir bilgisayarın hafızasında)?

Yığın, program görüntünüze ayrılan en yüksek bellek adresi olarak başlayan ve ardından oradaki değeri azaltan bellektir. Çağrılan işlev parametreleri ve işlevlerde kullanılan tüm geçici değişkenler için ayrılmıştır.

İki yığın var: kamu ve özel.

Özel öbek, programınızdaki son kod baytından sonra 16 baytlık bir sınırda (64 bit programlar için) veya 8 baytlık bir sınırda (32 bit programlar için) başlar ve ardından oradaki değer artar. Ayrıca varsayılan öbek olarak da adlandırılır.

Özel yığın çok büyürse yığın alanı üst üste binecek, yığın çok büyük olursa yığın üst üste gelecek. Yığın, daha yüksek bir adreste başlar ve düşük adrese doğru çalışır, uygun kesmekle yığını, özel yığın alanını aşacak ve kod alanını üst üste gelecek şekilde o kadar büyük yapabilirsiniz. O zaman püf noktası, koda girebileceğiniz kod alanından yeterince üst üste gelmektir. Bunu yapmak biraz zor ve bir program çökmesi riskini göze alıyorsunuz, ancak kolay ve çok etkili.

Ortak yığın, programınızın görüntü alanı dışındaki kendi bellek alanında bulunur. Bellek kaynakları azalırsa, sabit diske aktarılacak olan bu bellektir.

2) İşletim sistemi veya dil çalışma zamanı ne ölçüde kontrol edilir?

Yığın programcı tarafından denetlenir, özel öbek işletim sistemi tarafından yönetilir ve genel öbek hiç kimse tarafından denetlenmez, çünkü bu bir işletim sistemi hizmetidir - talepte bulunursunuz ya kabul edilir ya da reddedilir.

2b) Kapsamları nedir?

Hepsi program için küresel, ancak içerikleri özel, genel veya genel olabilir.

2c) Her birinin boyutunu ne belirler?

Yığın ve özel öbek boyutu, derleyici çalışma zamanı seçenekleriniz tarafından belirlenir. Genel yığın çalışma zamanında bir size parametresi kullanılarak başlatıldı.

2d) Hangisini daha hızlı yapan nedir?

Hızlı olacak şekilde tasarlanmamışlar, faydalı olacak şekilde tasarlandılar. Programcının bunları nasıl kullandığı “hızlı” mı yoksa “yavaş” mı olduğunu belirler

REF:

https://norasandler.com/2019/02/18/Write-a-Compiler-10.html

https://docs.Microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-getprocessheap

https://docs.Microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-heapcreate

3
ar18

programlama dilleri ile depolama tahsisi stratejileri 

C HAFIZA - STACK, HEAP VE STATİK

enter image description here MEMORY IN C – THE STACK, THE HEAP, AND STATIC

  1. PÇ: İşletim sistemi veya dil çalışma zamanı ne ölçüde kontrol edilir?

Bu önemli soru hakkında birkaç şey eklemek istiyorum: 

İşletim Sistemi ve Ortak Dil Çalışma Zamanı 

.NET Framework'ün Temel Bileşenleri enter image description here Net Framework 4.5 Mimarlık enter image description here

CLR Bileşenleri Components of CLR enter image description here enter image description here enter image description here

0
leonidaa