2016-02-19 1 views
5

Как сказано, каждому процессу присваивается 8 мб стека. Этот стек будет использоваться для хранения локальных переменных. Так что, если я беру массив размером больше, чем в стеке, он должен переполняться ??Переполненный стек с огромной локальной переменной?

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

Но я не могу получить результат!

+2

Когда вы переполняете стек, вы получаете * неопределенное поведение *, которое иногда может работать так, как ожидалось. Кроме того, компиляторы в наши дни довольно умны. Поскольку эти массивы не используются, почему компилятор действительно создает для них пространство? –

+0

Что происходит, когда вы меняете тип arr с 'int' на' volatile int'? –

+2

Кроме того, AFAIK, размер стека может варьироваться в разных системах. –

ответ

5

Добро пожаловать в мир оптимизирующих компиляторов!

Из-за правила as-if компилятор требуется только для создания чего-то, что будет иметь такие же наблюдаемые результаты, как и исходный код. Так компилятор, если свободно:

  • удалить неиспользуемые массивы
  • удалить пустую петле
  • магазина динамических массивов из основного снаружи стека - потому что главное специальная функция, которая должна быть вызвана только один раз в среде

Если вы хотите наблюдать за переполнения стека (плохой один, а не наш хороший сайт :-)), вам необходимо:

  • использовать некоторый код для заполнения массивов
  • компилировать со всей оптимизацией удалена и preferently в режиме отладки, чтобы сообщить компилятору делать то, что я написал так точно, как вы можете

Следующий код делает SIGSEGV с Clang 3.4.1 при компиляции в 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; 
} 

и даже этот код прекрасно работает при компиляции, как -O2 уровня оптимизации ... Компиляторы сейчас o умный для меня, и я недостаточно храбр, чтобы полностью изучить код сборки, который был бы единственным реальным способом понять, что на самом деле выполняется!

+0

@Lingxi: Ваш ответ был почти правильным. Если вы переведете его на C и отмените его (и напишите мне в комментарии), я выберу его, потому что мой - это просто объяснение вокруг вашего –

Смежные вопросы