Что означает стандарт С++ о переполнении стека?

Я взглянул на проект стандарта С++ 0x, и насколько я могу судить, в нем нет ничего о переполнении стека. Поиск "переполнения стека" не дает никаких результатов и ищет "стек". Я получил ссылки на разворачивание стека и std:: stack. Означает ли это, что не может быть совместимой реализации стандарта С++, поскольку не существует механизма, позволяющего обрабатывать ошибку, когда память исчерпывается локальным объектом, таким как огромный локальный массив?

Ответ на этот вопрос указывает, что по крайней мере стандарт C не упоминает переполнение стека.

Чтобы сделать конкретный вопрос, рассмотрим эту программу

// Program A
int identity(int a) {
  if (a == 0)
    return 0;
  char hugeArray[1024 * 1024 * 1024]; // 1 GB
  return identity(a - 1) + 1;
}
int main() {
  return f(1024 * 1024 * 1024);
}

и эта программа

// program B
int main() {
  return 1024 * 1024 * 1024;
}

Я думаю, что стандарт С++ не позволяет какой-либо реализации на С++ делать что-то, что заметно отличается от этих двух программ. В действительности программа A не будет работать на любой современной машине, поскольку она выделяет экзабайт памяти в стеке (представьте, что функция фактически использовала огромный массив, чтобы компилятор не мог безмолвно удалить его, чтобы не повредить). Предоставляет ли стандарт С++ программу A сбой?

Изменить: вопрос заключается не в том, определяет ли стандарт то, что происходит при переполнении стека, вопрос что он говорит, если что-то.

Ответ 1

Я не уверен, что это то, что вы ищете, но в Приложении B стандарта ISO С++ 03 есть следующее уведомление:

  • Поскольку компьютеры конечны, реализации С++ неизбежно ограничены в размерах программ, которые они может успешно обработать. Каждая реализация должна документировать те ограничения, которые известны. Эта документация может ссылаться на фиксированные пределы, где они существуют, сказать, как вычислить переменные пределы как функцию доступные ресурсы, или сказать, что фиксированные пределы не существуют или неизвестны.
  • Пределы могут ограничивать количества, которые включают в себя описанные ниже или другие.

(Мое внимание) Я полагаю, это означает, что компилятор совершенно легален, чтобы позволить одной из этих функций работать при сбое другой, при условии, что компилятор заявляет, какие ограничения существуют и как они вычисляются из ресурсов, система доступна.

Ответ 2

Поведение undefined, потому что стандарт не определяет, что происходит с программой, которая превышает пределы ресурсов. Обратите внимание, что в Приложении B спецификации указаны рекомендуемые пределы. Однако это приложение является ненормативным, и реализация может игнорировать это приложение, в том числе с различными пределами, чем указано там. В 1.4 [intro.compliance] спецификация говорит

Если программа не содержит нарушений правил в этом Международном стандарте, соответствующая реализация должна в пределах своих ресурсов принимать и правильно выполнять эту программу.

Ничто не говорит о том, что произойдет с программой, которая не содержит нарушения правил в IS, но которая не может быть принята и правильно выполнена в пределах ресурсов реализации. Следовательно, для такого случая поведение undefined.

Ответ 3

Переполнение стека прерывает механизм защиты, который имеет операционная система. Это не является признаком языка, так как все исполняемые машиной коды будут иметь такую ​​же защиту.

Если вы хотите поймать эту конкретную ошибку, вам нужно написать код конкретной операционной системы. Например, в Linux вам нужно поймать сигнал SIGSEGV (segmentation fault). Однако обратите внимание, что это также может быть вызвано замещением указателем NULL или любыми другими проблемами защиты памяти, а не только переполнением стека.

Не уверен в Windows, OSX или мобильных устройствах.

Ответ 4

Что происходит при переполнении стека, чрезвычайно зависит от системы (как для процессора, так и для ОС, а иногда и для компилятора, потому что до компилятора для вставки стековых зондов и других механизмов для безопасного расширения стека), поэтому невозможно задать конкретный ответ; лучшее, что можно было бы сделать, было бы предложить ответы, которые были бы предпочтительнее, если это позволит целевая платформа. Большинство нет; в то время как существует разумный способ обработки переполнения кучи, обработчик (a) может быть вызван, когда стек находится в несогласованном состоянии, с частично построенным фреймом стека на нем, и (b), вероятно, будет включать вызов обработчик... который требует пространства стека для кадра прерывания. POSIX указывает механизм sigaltstack(), но он также имеет ограничения, и ANSI C C/С++ не может разумно зависеть от соответствия POSIX.