Добро пожаловать в мир оптимизирующих компиляторов!
Из-за правила 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 умный для меня, и я недостаточно храбр, чтобы полностью изучить код сборки, который был бы единственным реальным способом понять, что на самом деле выполняется!
Когда вы переполняете стек, вы получаете * неопределенное поведение *, которое иногда может работать так, как ожидалось. Кроме того, компиляторы в наши дни довольно умны. Поскольку эти массивы не используются, почему компилятор действительно создает для них пространство? –
Что происходит, когда вы меняете тип arr с 'int' на' volatile int'? –
Кроме того, AFAIK, размер стека может варьироваться в разных системах. –