Чтобы проанализировать подобные загадки, всегда полезно взглянуть на сгенерированный код. Я предполагаю, что ваша конкретная версия компилятора делает что-то другое, потому что мой segfaults с -O0, но не с -O1.
Из вашей программы # 1: g ++ a.c -g -O0 , а затем objdump -S a.out
int main(int argc, char * argv[])
{
8048484: 55 push %ebp
8048485: 89 e5 mov %esp,%ebp
Это стандартный кадр стека. Здесь нечего видеть.
8048487: 83 e4 f0 and $0xfffffff0,%esp
Выровняйте стек на кратное 16, на всякий случай.
804848a: 81 ec 30 00 b0 00 sub $0xb00030,%esp
Выделите 0xB00030 байт стекового пространства. Это 1024 *1024* 11 + 48 байтов. Нет доступа к памяти еще, поэтому не исключение. Дополнительные 48 байтов предназначены для внутреннего использования компилятором.
8048490: 8b 45 0c mov 0xc(%ebp),%eax
8048493: 89 44 24 1c mov %eax,0x1c(%esp) <--- SEGFAULTS
При первом обращении к стеку выходит за пределы ulimit, поэтому он вызывает ошибки.
8048497: 65 a1 14 00 00 00 mov %gs:0x14,%eax
Thiis является стековым защитником .
804849d: 89 84 24 2c 00 b0 00 mov %eax,0xb0002c(%esp)
80484a4: 31 c0 xor %eax,%eax
char buf[1024*1024*11] = {0};
80484a6: 8d 44 24 2c lea 0x2c(%esp),%eax
80484aa: ba 00 00 b0 00 mov $0xb00000,%edx
80484af: 89 54 24 08 mov %edx,0x8(%esp)
80484b3: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
80484ba: 00
80484bb: 89 04 24 mov %eax,(%esp)
80484be: e8 d1 fe ff ff call 8048394 <memset@plt>
Инициализировать массив, вызывая memset
return 0;
80484c3: b8 00 00 00 00 mov $0x0,%eax
}
Как вы можете видеть, segfault происходит, когда к внутренним переменным обращаются, потому что они оказываются ниже большого массива (они должны быть, потому что есть защитник стека, чтобы обнаружить разрушение стека).
Если вы компилируете с оптимизацией, компилятор замечает, что вы ничего не делаете с массивом, и оптимизирует его. Так что нет сигсег.
Возможно, ваша версия GCC немного перегружена в режиме без оптимизации и удаляет массив. Мы можем проанализировать его дальше, если вы разместите вывод objdump -S a.out .