Что стандарт C ++ говорит о переполнении стека? - PullRequest
11 голосов
/ 06 июля 2011

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

Ответы на этот вопрос указывает, что по крайней мере в стандарте 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;
}

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

Редактировать: Вопрос не в том, должен ли стандарт определять, что происходит при переполнении стека, вопрос в том, что этоговорит, если что.

Ответы [ 4 ]

14 голосов
/ 06 июля 2011

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

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

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

4 голосов
/ 06 июля 2011

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

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

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

1 голос
/ 06 июля 2011

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

1 голос
/ 06 июля 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...