Yığın sınırı


10

Son zamanlarda farklı işletim sistemlerine sahip üç cihazda bir yığının limitini test ettim (limite göre, yığının sahip olabileceği maksimum seviye sayısını kastediyorum) ve 2 ^ 16 seviyesine her bastığımda bana verdiğini fark ettim. taşma hatası ve 2 ^ 16-1 koyduğumda düzgün çalışıyor.

Benim sorum şu - bu doğru mu? Yığın tanımı gereği maksimum 2 ^ 16-1 limiti var mı veya işletim sistemine bağlı mı?


5
here i mean by limit the maximum number of levels that can the stack haveseviye nedir?
tkausl


3
Nasıl test ediyorsunuz? Giriş olarak 2 bayt (dword) kullanıyor musunuz?
pro3carp3

6
Hangi programlama dilini kullanıyorsunuz? Sabit bir sayıdaki bu kadar keskin bir sınırlama, işletim sisteminin tahsis edilen yığın boyutuna göre değil, dilinize özgü çalışma zamanınız için kasıtlı bir sınırlama olduğunu gösterir. Örneğin, python, gerçek bir yığın taşmasına
çarpmanızı

Yanıtlar:


20

Bu, işletim sistemine özgüdür (ve bilgisayara özgü) ve bazı işletim sistemlerinde limiti yapılandırmak (hatta arttırmak) için bazı yollarınız vardır. Hatta bazı derleyiciler ( bazı sınırlı C kodu için son GCC dahil ) bazı kuyruk çağrılarını optimize edebildiğinden, derleyiciye özeldir (veya programlama-dil-uygulamanıza özgü) .

(bazı programlama dili spesifikasyonları kuyruk çağrısı optimizasyonları gerektirir , örneğin R5RS )

Sorunuzun mantıklı olduğundan emin değilim (ve kesinlikle 2 16 limitiniz değil). Linux masaüstümde (Debian / Sid / x86-64, Linux 4.9 çekirdek, 32Gb RAM, Intel i5-4690S), 8 megabayta kadar bir çağrı yığını alabilirim (ve eğer gerçekten istersem bu limiti artırabilirim) ).

Çoklu iş parçacığı ve ASLR , sorunuzu daha karmaşık hale getiriyor . Bkz. Örneğin pthread_attr_setstack (3) . Ayrık yığınlar (genellikle Go uygulamaları tarafından kullanılır ) ve devam geçiş tarzı hakkında da okuyun . Ayrıca bu cevaba bakınız .

Ne için değer, ben sadece aşağıdaki C99 (ve ayrıca C11) kodunu denedim:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void recfun(int x, int d) {
  printf("start recfun x=%d d=%d\n", x, d);
  fflush(NULL);
  if (d>0)
    recfun(x+1, d-1);
  printf("end recfun x=%d d=%d\n", x, d);
}

int main(int argc, char**argv) {
  int md = argc>1?atoi(argv[1]):10000;
  printf ("start md=%d\n", md);
  recfun(0, md);
  printf("end md=%d clock=%ld µs\n", md, clock());
}    
// eof recur.c

ve bu recurprogramı (GCC 6 as ile derlenmiş gcc -Wall -O recur.c -o recur) olarak recur 161000 (2 16 limitinizin çok üzerinde ) çalıştırabildim. Bununla recur 256000birlikte çalıştı. İle recur 456000(bir kırıldı yığın taşması düzeyi için x=272057). Diğer testler için sabrım yok. Bunu bilgisayarınızda deneyin. Optimizasyon istemeyi unutmayın.

Genel bir kural (masaüstü bilgisayarlar, dizüstü bilgisayarlar, tabletler için) çağrı yığınınızı bir megabaytın altında tutmak olabilir.

Ayrıca geçerek -fstack-usage için gcc ben şu alıyorum recur.sudosyası (sayılar, bayt benim 8MB yığın sınırı sezgi tutarlıdır; unutma mainyaparken çekirdek tarafından yüklenen çağrı çerçeve ve daha da önemlisi, ilk yığın düzeni, (2 execve ) ..., crt0 için ):

 recur.c:5:10:recfun    32  static
 recur.c:13:9:main  16  static

PS. Arduino'mda sadece 2Kbyte RAM'e sahip bir Atmega328 var, bu yüzden kesinlikle bu kadar çok tekrarlayamazsınız. Sanırım Arduinos'da en fazla pratik olarak sadece birkaç yüz yığın çerçevesi mümkün.


3

Bir işlemin ana iş parçacığı için yığın boyutu Windows bağlayıcı tarafından ayarlanır. Varsayılan değer 1 MB'dir, ancak / STACK anahtarı ile ayarlanabilir. Daha sonra oluşturulan iş parçacıkları CreateThread işlevinin dwStackSize parametresini kullanabilir.

Yani ... çeşitli Windows işletim sistemlerini test ediyorsanız, en az NT4.0'dan beri hepsi aynı varsayılan yığın boyutuna sahipti.

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.