Yığın üzerinde her şey çok daha verimli bir şekilde yapılabiliyorsa neden bir yığına ihtiyacımız var?


24

Bu aslında biraz ben yaklaşık dün sorulan soruya ilişkilidir bir Stack hem neden ve bir Öbek gereklidir & bir basit olması için, kullandığımız uygulamalarda bugün (ve neden biz sadece yerine her ikisinin bir Heap ile gidemez gitmek için tekil standart).

Bununla birlikte, cevapların birçoğu, bir Yığın'ın Yığını tahsis etmeye / referans vermeye çalışmaktan çok daha yüzlerce (veya binlerce kez) daha hızlı olması nedeniyle yeri doldurulamayacağını göstermiştir. Yığınları ortadan kaldırırsak dinamik depolama tahsisinde bir sorun olduğunu biliyorum, ancak bunun etrafında bir yol veya dinamik bellek tahsisini idare edebilecek şekilde Yığını iyileştirmenin bir yolu yok mu?


4
Önceki sorunuzdan iki alıntı: "En önemli dezavantajı sınırlı alana sahip olmasıdır ve bu yüzden büyük nesneleri içinde tutmak veya uzun ömürlü nesneler için kullanmaya çalışmak hem kötü fikirlerdir" hem de "yığınlar son derece verimlidir LIFO (ilk giren ilk çıkar) kurallarına uyan veri yönetimi yapısı. "
Cascabel

2
Öncülün hatalı - her şey yığında çok daha verimli bir şekilde yapılamaz. Ne olduğunu - Bu aldığınız cevaplara hiçbir çelişki olduğunu olabilir çok daha hızlı orada yapılabilir yığın yapılabilir.
Ingo,

... donanımınızın yığında veya yığında göreceli bir adreslemesi olduğunu varsayarsak.
Ritch Melton

3
İkna oldum. Yapalım diyorum.
JeffO,

Yanıtlar:


25

Yığınlardaki sorun, yığının tepesinde olmadığı sürece belleği "boşaltamaz". Örneğin, farklı boyutlarda 3 şey ayırdığınızı varsayalım:

a = allocate(2000000); // 2000000 bytes
b = allocate(1);
c = allocate(5000000);

Yığın aaltta, bortada ve cüstte olacaktır. Özgür kalmak istiyorsak bu sorun çıkarır b:

free(b); // b is not on top! We have to wait until c is freed!

Çözüm, tüm verileri sonradan taşımak bve eğer sonra gelmek üzere kaydırmaktır a. Bu çalışır, ancak bu durumda 5000000 kopya gerektirir - bir yığından çok daha yavaş olacak bir şey.

Bu yüzden bir yığınımız var. Tahsis bir yığından ( O(log n)vs O(1)) daha yavaş olsa da , yığınlar, bir yığınınkiyle O(log n)karşılaştırıldığında, keyfi bir yerde belleği serbest bırakmayı sağlar.O(n)


4
Bununla ilgili, Facebook'un kaldırmasını istediğinizde içeriği diskten kaldırmaması, yalnızca işaretçiyi kaldırmasıdır. Açıkçası, disk üzerindeki eşdeğeri boşluğu bulmaya veya bulmaya çalışmanın yükü, veri yazdıkları oranlarda çok zaman alıyor, bu yüzden her şeyi diskin yüksek su işaretine ekliyorlar.
Paul Tomblin

Peki, facebook diskleri yığın olarak görülebilir. Ayrıca hazne diskleri için bir çeşit çöp koleksiyonuna sahip olduklarından eminim.
deadalnix,

2
@deadalnix Aslında normalde daha büyük miktarda bellek için kullanılan yığın yerine devasa bir yığın kullanmanın bir örneğidir. Facebook olsa özel bir durumdur. Veri, ayrılma işleminin büyüme hızında önemli bir fark yaratmadığı için kaldırıldığından çok daha hızlı eklenir - kasıtlı olarak O (1) tahsisini almak için tasarıma bellek sızıntıları ekleyebilirsiniz.
Tom Clarkson,

7
@PaulTomblin FB'nin içeriği kaldırmamasının ana nedeni, karları için mayın
açabilmeleri

5
Facebook doesn't remove content from its disk when you ask it to remove it, it just removes the pointer to it- Esasen, herhangi bir işletim sistemindeki bir dosyayı sıradan bir şekilde sildiğinizde ne olur.
Robert Harvey,

5

Yığın iş parçacığı başınadır, Yığın işlem çapında

100 iş parçacığı varsa tüm iş öğelerini bir kuyruğa koyarsam, 100 iş parçacığının herhangi birinin görebileceği şekilde iş öğelerini tam olarak nereye tahsis ederim?

Başka hafıza tipleri de var.

Örn. Hafıza haritalı dosyalar, paylaşılan hafıza, G / Ç haritalanmış (çekirdek modu). Verimlilik argümanı bu durumlarda bir tür tartışmadır.


4

Bir yığın, referans göstergesinin tutulduğu (genellikle donanım tarafından desteklenir) bir LIFO (ilk giren ilk çıkar) yapısıdır. Bunu söyledikten sonra, yığın yerine yığında tahsis etmeye çalıştığınız herhangi bir şeyin, bu yığının en üstünde her işlevde yerel bir değişken olması gerekir. Bu nedenle, bir yığına karşı ana neden, ana () yordamınızın, programınızın kullandığı tüm veri yapılarını (programınızın tamamı boyunca olması amaçlanmıştır) tüm veri yapılarının tahsis ettiği gibi önceden tahsis etmesi gerekmesidir. işlev çağrıları içinde, bu işlev çağrıları geri döndüğünde ve çerçeveleri veya etkinleştirme kayıtları yığından çıkarıldığında sonuçta kaldırılır.


3
LIFO, FIFO değil.
Pubby

bazen FILO olarak da adlandırılır;)
oenone

3

Yığınlar, Son Giren İlk Çıkar (LIFO) kurallarına uyan bellek ayırma işlemlerinde harika çalışır; yani, belleği ayırdığınız sırayla serbest bırakırsınız. LIFO çok yaygın, belki de en yaygın olanı, bellek ayırma düzenidir. Ama bu tek kalıp değil, hatta ortak olan tek kalıp değildir. Çok çeşitli sorunların üstesinden gelebilecek verimli bir program yazmak için, daha karmaşık bir altyapıya sahip olsa bile, daha az yaygın kalıplara izin vermeliyiz.

Bir paragraf için tüm metaları alabilirsem: başlangıç ​​seviyesindesiniz, başlangıç ​​olarak sadeliği ve siyah beyaz kurallarını değerlendiriyorsunuz. Bununla birlikte, bir başlangıç ​​olarak, yalnızca bilgisayar programları tarafından barındırılması gereken sorunların ve kısıtlamaların bir dizi gözetleme deliği görünümüne sahipsiniz. 75 yıldır devam eden aktif bir gelişim içinde olan bir teknolojiye giriyorsunuz. İşlerin neden böyle olduklarını sormakta yanlış bir şey yoktur, ancak cevap genellikle "Evet, basit, yalındır yöntemi 50 yıl önce denedik ve tüm dersler için çok iyi çalışmadığı ortaya çıktı." Sorunlardan dolayı, daha karmaşık bir şey yapmak zorunda kaldık ”. Bir teknoloji ilerledikçe, sadelik genellikle verimlilik ve esnekliğe yol açmak zorundadır.


0

Başka bir örnek için, kapanışlar. Eğer pop yığarsanız, kapatmanızın aktivasyon kaydını kaybedebilirsiniz. Yani, bu anonim fonksiyonun ve verilerinin devam etmesini istiyorsanız, çalışma zamanı yığından başka bir yerde saklamanız gerekir.


0

Öbek depolama ayırmak için diğer birçok neden arasında.

Bir nesnenin adresini geri arayan bir programa geri aktarmak istiyorsanız, yığın değişkeninin adresini iletmeyin, çünkü yığın depolama yeniden kullanılacak ve muhtemelen bir sonraki fonksiyon tarafından yazılabilir. Sonraki fonksiyonlara yapılan çağrılarla üzerine yazılmayacağından emin olmak için malloc () işlevini kullanarak gerekli depolama alanını edinmeniz gerekir.

İşlev öğelerinden yığın öğelerinin adreslerini aradığınız işlevlere aktarabilirsiniz, çünkü programınız "geri dönene ()" kadar varolmasını garanti edersiniz. Ancak, işleviniz geri döndüğünde, tüm yığın depolama kapmak için hazırdır.

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.