Понимание объявления массива в C - PullRequest
0 голосов
/ 17 ноября 2018

Я пытаюсь понять, как Стандарт C объясняет, что объявление может вызвать ошибку. Рассмотрим следующий довольно простой код:

int main()
{
    char test[1024 * 1024 * 1024];
    test[0] = 0;
    return 0;
}

* 1004 Demo *

Это сегфальц. Но следующий код не делает:

int main()
{
    char test[1024 * 1024 * 1024];
    return 0;
}

Демо

Но когда я скомпилировал его на своей машине, последний тоже был поврежден. Основная функция выглядит как

00000000000008c6 <main>:                        
 8c6:   55                      push   %rbp                            
 8c7:   48 89 e5                mov    %rsp,%rbp                                         
 8ca:   48 81 ec 20 00 00 40    sub    $0x40000020,%rsp        
 8d1:   89 bd ec ff ff bf       mov    %edi,-0x40000014(%rbp) // <---HERE    
 8d7:   48 89 b5 e0 ff ff bf    mov    %rsi,-0x40000020(%rbp)                      
 8de:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
 8e5:   00 00                       
 8e7:   48 89 45 f8             mov    %rax,-0x8(%rbp)
 8eb:   31 c0                   xor    %eax,%eax
 8ed:   b8 00 00 00 00          mov    $0x0,%eax       
 8f2:   48 8b 55 f8             mov    -0x8(%rbp),%rdx
 8f6:   64 48 33 14 25 28 00    xor    %fs:0x28,%rdx
 8fd:   00 00                              
 8ff:   74 05                   je     906 <main+0x40>
 901:   e8 1a fe ff ff          callq  720 <__stack_chk_fail@plt>
 906:   c9                      leaveq
 907:   c3                      retq
 908:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
 90f:   00

Насколько я понял, произошла ошибка при попытке mov %edi,-0x40000014(%rbp).

Я попытался найти объяснение в N1570 , Section 6.7.9 Initialization, но, похоже, оно не подходит.

Так как же Стандарт объясняет это поведение?

1 Ответ

0 голосов
/ 17 ноября 2018

Результат зависит от реализации

Я могу придумать несколько причин, почему поведение должно отличаться

  • компилятор видит, что переменная не используется, никаких побочных эффектов, и оптимизирует ее (даже без уровней оптимизации)
  • изменение размера стека по запросу. Поскольку в эту переменную еще нет записей, зачем теперь изменять размер стека?
  • компиляторам не нужно использовать стек для автоматической памяти. Компилятор может выделить память, используя malloc, и освободить ее при выходе. Использование кучи позволит выделить 1 Гб без проблем
  • размер стека установлен в 1Gb:)
...