Вдохновленный этим вопросом .
Очевидно в следующем коде:
#include
int _tmain(int argc, _TCHAR* argv[])
{
if( GetTickCount() > 1 ) {
char buffer[500 * 1024];
SecureZeroMemory( buffer, sizeof( buffer ) );
} else {
char buffer[700 * 1024];
SecureZeroMemory( buffer, sizeof( buffer ) );
}
return 0;
}
скомпилирован с размером стека по умолчанию (1 мегабайт) с помощью Visual C ++ 10 с оптимизацией на (/ O2) a Переполнение стека происходит из-за того, что программа пытается выделить в стеке 1200 килобайт.
Приведенный выше код, конечно, слегка преувеличен, чтобы показать проблему - использует большое количество стека довольно глупым способом. Однако в реальных сценариях размер стека может быть меньше (например, 256 килобайт), и может быть больше ветвей с меньшими объектами, которые вызовут общий размер выделения, достаточный для переполнения стека.
Это не имеет смысла. В худшем случае будет 700 килобайт - это будет кодовый путь, который создает набор локальных переменных с наибольшим общим размером на этом пути. Обнаружение этого пути во время компиляции не должно быть проблемой.
Таким образом, компилятор создает программу, которая пытается выделить даже больше памяти, чем в худшем случае. Согласно , этот ответ LLVM делает то же самое.
Это могло быть недостатком в компиляторе или могла быть какая-то реальная причина для этого. Я имею в виду, что, возможно, я просто не понимаю чего-то в дизайне компиляторов, что могло бы объяснить, почему такое распределение необходимо.
Почему компилятор хочет, чтобы программа выделяла больше памяти, чем требуется коду в худшем случае?