В зависимости от компилятора следующий код:
int main()
{
srand( 0 );
if( rand() ) {
char buffer[600 * 1024] = {};
printf( buffer );
} else {
char buffer[500 * 1024] = {};
printf( buffer );
}
return 0;
}
при запуске в системе с максимальным размером стека, равным 1 мегабайту, либо печатает пустую строку, либо сбой при переполнении стека.
Разница заключается в том, что разные компиляторы распределяют автоматическое хранилище по-разному. Большинство компиляторов выделяют хранилище для всех объектов при запуске функции, поэтому в приведенном выше коде они выделяют 600 + 400 = 1100 килобайт, что приводит к переполнению стека. Некоторые компиляторы более умны, и они видят, что эти два массива никогда не могут быть доступны одновременно, поэтому они повторно используют одну и ту же память и выделяют только 600 килобайт, и программа работает нормально.
Теперь в "Стандарте" говорится (3.7/1), что продолжительность хранения определяет минимальное потенциальное время жизни хранилища, а затем (3.7.2/1), что хранение для этих объектов [с автоматической продолжительностью] продолжается до тех пор, пока блок, в котором они создаются.
Я не понимаю, как применять 3.7/1 и 3.7.2/1 вместе. Один говорит, что длительность минимального потенциала, а другая говорит явно, что она длится до тех пор, пока не будет существовать блок. Похоже, в соответствии с первыми обе стратегии распределения являются законными, но второй требует использовать только стратегию распределения "повторного использования".
Как 3.7/1 и 3.7.2/1 сосуществуют? Является ли законным выделять больше памяти, чем требуется в самом худшем случае (первая стратегия)?