2016-02-19 12 views
5

Jak się mówi, do każdego procesu przydzielono 8 mb stosu. Ten stos będzie używany do przechowywania zmiennych lokalnych. Więc jeśli wziąć tablicę o wielkości max niż stosu, to musi się przepełnić ??Przepełniony stos z ogromną zmienną lokalną?

int main() 
{ 
int arr[88388608]; 
int arr1[88388608]; 
int arr2[88388608]; 
while(1); 
return 0; 
} 

Ale nie mogę uzyskać wyniku!

+2

Po przepełnieniu stosu uzyskujesz * niezdefiniowane zachowanie *, które czasami może działać zgodnie z oczekiwaniami. Również kompilatory w tych dniach są dość inteligentne. Ponieważ te tablice są nieużywane, dlaczego kompilator rzeczywiście powinien dla nich utworzyć przestrzeń? –

+0

Co się stanie, gdy zmienisz typ arr z 'int' na' volatile int'? –

+2

Ponadto, AFAIK, rozmiar stosu może się różnić w zależności od systemu. –

Odpowiedz

5

Witamy w świecie optymalizacji kompilatorów!

Z powodu reguły "jak gdyby" kompilator musi tylko zbudować coś, co dałoby identyczne wyniki, co oryginalny kod. więc kompilator jeśli swobodę:

  • usunąć nieużywane tablice
  • usunąć pustej pętli
  • przechowywać dynamiczne tablice z głównego zewnątrz stosu - bo główny jest specjalna funkcja, która zostanie wywołana tylko raz przez środowisko

Jeśli chcesz obserwować przepełnienie stosu (złe jednym, nie nasza nice site :-)), należy:

  • użyć kodu, aby wypełnić tablice
  • skompilować z wszystkimi optymalizacji usunięte i preferently w trybie debugowania, aby poinformować kompilator robić to, co napisałem tak dokładnie, jak to tylko możliwe

Poniższy kod robi SIGSEGV z dzyń 3.4.1 gdy kompilowany jako cc -g foo.c -o foo

#include <stdio.h> 

#define SIZE 88388608 

void fill(int *arr, size_t size, int val) { 
    for (size_t i=0; i<size; i++) { 
     arr[i] = val; 
    } 
}  
int main() { 
    int arr[SIZE]; 
    int arr1[SIZE]; 
    int arr2[SIZE]; 

    fill(arr, SIZE, 0); 
    fill(arr1, SIZE, 0); 
    fill(arr2, SIZE, 0); 
    printf("%d %d %d\n", arr[12], arr1[15], arr2[18]); 

    return 0; 
} 

i nawet ten kod działa poprawnie, gdy skompilowany jako -O2 poziomu optymalizacji ... Kompilatory są teraz o sprytny dla mnie, a ja nie jestem na tyle odważny, aby dokładnie przyjrzeć się kodowi montażowemu, który byłby jedynym prawdziwym sposobem zrozumienia tego, co faktycznie zostało wykonane!

+0

@Lingxi: Twoja odpowiedź była prawie poprawna. Jeśli przetłumaczysz go na C i przywrócisz go (i wypytasz w komentarzu), zrobię to, ponieważ moje jest tylko wytłumaczeniem wokół ciebie –

Powiązane problemy