Limite dello stack


10

Recentemente ho testato il limite di uno stack su tre dispositivi con diversi sistemi operativi (per limite, intendo il numero massimo di livelli che può avere lo stack) e ho notato che ogni volta che raggiungo 2 ^ 16 livelli mi dà errore di overflow e quando inserisco 2 ^ 16-1 funziona correttamente.

Quindi la mia domanda è: è vero? Lo stack ha il limite massimo 2 ^ 16-1 per definizione o dipende dal sistema operativo?


5
here i mean by limit the maximum number of levels that can the stack havequal è il livello?
martedì


3
Come lo testate? Stai usando un 2 byte (dword) come input?
pro3carp3,

6
Quale linguaggio di programmazione stai usando? Un limite così acuto a un numero fisso indica che è una limitazione deliberata dal runtime specifico della lingua e non dalla dimensione dello stack allocata dal sistema operativo. Ad esempio, Python sembra imporre un limite di 1000 per impostazione predefinita per impedire che si verifichi un overflow dello stack reale (il ripristino da uno overflow dello stack reale è difficile)
CodesInChaos,

Risposte:


20

È fortemente specifico del sistema operativo (e specifico del computer) e su alcuni sistemi operativi hai alcuni modi per configurare (e persino aumentare) il limite. È persino specifico del compilatore (o specifico del tuo linguaggio di programmazione), dal momento che alcuni compilatori (incluso GCC recente per qualche tipo limitato di codice C) sono in grado di ottimizzare alcune chiamate di coda .

(alcune specifiche del linguaggio di programmazione richiedono ottimizzazioni delle chiamate di coda, ad es. R5RS )

Non sono sicuro che la tua domanda abbia un senso (e certamente non il tuo limite di 2 16 ). Sul mio desktop Linux (Debian / Sid / x86-64, kernel Linux 4.9, RAM 32Gb, Intel i5-4690S), potrei avere uno stack di chiamate fino a 8 megabyte (e potrei aumentare quel limite, se volessi davvero ).

Il multi-threading e ASLR stanno rendendo la tua domanda molto più complessa . Vedi ad esempio pthread_attr_setstack (3) . Leggi anche informazioni sugli stack divisi (spesso utilizzati dalle implementazioni Go ) e sullo stile del passaggio di continuazione . Vedi anche questa risposta.

Per quello che vale, ho appena provato il seguente codice C99 (e anche C11):

#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

e sono stato in grado di eseguire quel recurprogramma (compilato con GCC 6 as gcc -Wall -O recur.c -o recur) come recur 161000 (molto al di sopra del limite di 2 16 ). Con recur 256000ha anche funzionato. Con recur 456000esso si è schiantato (con un overflow dello stack per livello x=272057). Non ho la pazienza per altri test. Provalo sul tuo computer. Non dimenticare di chiedere ottimizzazioni.

Una regola empirica (per desktop, laptop, tablet) potrebbe essere quella di mantenere lo stack delle chiamate al di sotto di un megabyte.

Passando anche -fstack-usage a gcc sto ottenendo il seguente recur.sufile (i numeri sono in byte, coerenti con la mia intuizione del limite dello stack da 8 Mb; non dimenticare il mainframe di chiamata e, soprattutto, il layout dello stack iniziale, installato dal kernel quando si esegue execve (2 ) ..., per crt0 ):

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

PS. Il mio Arduino ha un Atmega328 con solo 2Kbyte di RAM, quindi sicuramente non può ricorrere così tanto. Immagino che solo poche centinaia di frame stack siano praticamente possibili su Arduinos.


3

Dimensione dello stack per il thread principale di un processo di Windows impostato dal linker. L'impostazione predefinita è 1 MB, ma può essere regolata con l'opzione / STACK. I thread creati in seguito possono utilizzare il parametro dwStackSize della funzione CreateThread.

Quindi .. se stai testando vari sistemi operativi Windows, hanno tutti le stesse dimensioni dello stack predefinite almeno da NT4.0.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.