Ne kadar yığın kullanımı çok fazla?


22

Son zamanlarda C veya C ++ yazarken, Java'daki gibi bir seçenek olduğu için yığın üzerindeki tüm değişkenlerimi bildireceğim.

Ancak, yığın üzerinde büyük şeyler bildirmenin kötü bir fikir olduğunu duydum.

  1. Neden böyle oluyor? Yığın taşması söz konusu, ancak bunun neden olduğu konusunda çok net değilim.
  2. Yığında ne kadar çok şey var?

Yığına 100MB dosyaları koymaya çalışmıyorum, sadece bir düzine kilobayt dizeleri dize arabellekleri veya başka bir şey olarak kullanmam. Bu çok fazla yığın kullanımı mı?

(Yinelenirse üzgünüm, Stack Overflow'a referans vererek yığının aranması devam ediyor. Bir çağrı yığını etiketi bile yok, sadece soyut olanı kullandım.)


1
"Yığına 100MB dosyaları nasıl koyarsınız?" Tampon ve konteyner uygulamaları (ve std :: string gibi) genellikle yüklerini depolamak için yığını kullanır.
Murphy

2
Özyineleme dahil oluncaya kadar işlev / yöntem başına adil miktarda yığın kullanımından kurtulabilirsiniz, daha sonra özyinelemeli derinliğe karşı yeteneklerinizi ciddi şekilde sınırlama riskiniz vardır, bu nedenle özyinelemeli işlevler içinde az yerel kullanmak istersiniz. değişken / yığın alanı mümkün olduğunca.
Erik Eidt

3
C & C ++ 'nın farklı olduğuna dikkat edin. Yerel bir std::vector<int>değişken çok fazla yığın alanı yemez, verilerin çoğu yığın halindedir.
Basile Starynkevitch

Yanıtlar:


18

İşletim sisteminize bağlıdır. Windows'da, bir yığının tipik maksimum boyutu 1MB, tipik bir modern Linux'ta 8MB'dir, ancak bu değerler çeşitli şekillerde ayarlanabilir. Tüm çağrı yığınındaki yığın değişkenlerinizin toplamı (dönüş adresleri, yığın tabanlı bağımsız değişkenler, dönüş değeri yer tutucuları ve hizalama baytları gibi düşük düzeyli ek yük dahil) bu sınırı aşarsa, genellikle kurtarma şansı olmadan programı.

Birkaç kilobayt genellikle iyidir. Onlarca kilobayt tehlikelidir çünkü özetlemeye başlar. Yüzlerce kilobayt çok kötü bir fikir.


1
Tipik yığın bugün 2016'da birkaç megabayt (yani genellikle birden fazla, ancak muhtemelen bir düzineden az) sınırlamıyor mu? Linux masaüstümde, varsayılan olarak 8Mbayt ...
Basile Starynkevitch

"[[]] Linux'ta, bir yığın için tipik maksimum boyut 1 MB'dir" $ ulimit -asistemimde diğerleri arasında döner stack size (kbytes, -s) 8192.
Murphy

9

Tek geçerli cevap belirsizdir: "çok fazla yığının taşmasıdır."

Programın giriş noktası ve söz konusu işlev arasındaki her kod satırının uygulanması üzerinde tam kontrol sahibi değilseniz, ne kadar yığının kullanılabilir olduğu konusunda herhangi bir varsayımda bulunamazsınız. Örneğin, bu işlevi çağırmanın hiçbir zaman yığın taşmasına neden olmayacağını garanti edemezsiniz:

void break_the_camels_back()
{
    int straw;
    ...
}

Modern Unix'lerde varsayılan 8 MiB yığını, özellikle benim gibi 8 bit yığın işaretleyicili CPU'ları hatırlamaya yetecek kadar moruk olan biri için yığınlar giderken oldukça fazla yer kaplıyor. Pratik gerçek şu ki, denemeden onu havaya uçurmak olası değildir. Bunu yaparsanız, yığın sınırını aşmak genellikle bir segmentasyon ihlali olarak kabul edilir ve bunu algılamak için yeterli bellek yönetimine sahip sistemler birSIGSEGV gerçekleştiğinde gönderir.

Birkaç seçeneğiniz var. Birincisi, ne kadar yığının mevcut olduğunu tahmin etmemek ve sisteme sormaktır. POSIX ile uyumlu olan her getrlimit(2)şeyin size üst limiti belirten bir işlevi olacaktır. RLIMIT_STACKistediğiniz özel sınırdır. İkincisi, programlarınızın ne kadar yığın kullandığını izlemek ve buna bağlı olarak dinamik bellek ayırmaya karşı otomatik değişkenler hakkında kararlar almaktır. Bildiğim kadarıyla, yığının ne kadarının kullanıldığını belirleyen standart işlevler yoktur, ancak benzeri programlar valgrindsizin için analiz edebilir.


4

Yığında 10.000 baytlık bir dizi ayırırsanız, o dizinin boyutu sınırlıdır. 10.000 çok olabilir, ancak 10.001 bayta ihtiyacınız varsa programınız çökebilir veya kötüleşebilir. Bu durumda, ihtiyacınız olan boyuta uyum sağlayan bir şey istersiniz ve yığının üzerinde bir şey olmaz.

Yığında dize arabellekleri için sabit boyutlu diziler sorun değil, çünkü bellekte yığının üzerinde kalıyorlar, sorunlu çünkü sabit boyutlu arabellekler gerçekleşmeyi bekleyen önemli bir sorundur.

Ancak, C ++ kullanırsanız ve örneğin yığın üzerinde bir std :: string veya std :: vec bildirirseniz, yığında ne olduğunu gerçekten sabit ve küçük bir boyutta olacaktır. Gerçek veriler öbekte saklanacaktır. Std :: string örneğinde bir milyon karakter depolayabilirsiniz ve yığın üzerinde çok az miktarda veri (uygulamaya bağlı olarak genellikle 8 ila 24 bayt) ve yığın üzerinde bir milyon bayt alır.


2

Peki 1 MB * nix için iyi bir tahmindir. Yineleme, yığın tahsisleriyle birlikte yığın taşmasının önemli bir nedeni olabilir. Bununla birlikte, çoğu durumda, yüzeysel olarak yığın üzerine yerleştirilemeyecek kadar büyük görünen tanrı nesneleri, yığın üzerindeki dahili belleklerini yönetmek ve yığını yalnızca yığın patlatıldığında otomatik olarak yok edilmenin bir yolu olarak kullanmak için iyi tasarlanmıştır. Yıkıcı, dahili olarak yönetilen devasa bellek parçalarını serbest bırakacak. Standart kaplar bu şekilde ve paylaşılan / benzersiz işaretçiler de bu şekilde tasarlanmıştır.

Önemli olan char [1024 * 1024] gibi yığın üzerinde büyük ham mem parçaları tahsis etmemek ve yığın tahsislerini sarmak ve yığını yalnızca yıkıcıyı otomatik olarak çağırmak için kullanmak üzere sınıflar tasarlamaktı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.