Почему переполнение стека не вызывает ошибок в Visual C ++? - PullRequest
4 голосов
/ 05 августа 2010

В Microsoft Visual C ++ 2010 я создал программу, которая намеренно вызывает переполнение стека.Когда я запускаю программу, используя «start debugging», возникает ошибка при переполнении стека.Когда я запускаю его с помощью «запуска без отладки», не выдается никакой ошибки, и программа просто молча завершается, как будто она успешно завершена.Может ли кто-нибудь объяснить мне, что происходит?Также другие компиляторы не генерируют ошибки при переполнении стека?

(я подумал, что это правильное место, чтобы задать вопрос о переполнении стека.)

Ответы [ 6 ]

9 голосов
/ 05 августа 2010

C ++ не будет держать вас за руку, как это делает управляемая среда.Переполнение стека означает неопределенное поведение.

5 голосов
/ 05 августа 2010

Переполнение стека - неопределенное поведение.Компилятор вполне может игнорировать его или вызывать любое событие.

4 голосов
/ 05 августа 2010

Потому что, когда ваш стек процессов переполняется, он больше не является допустимым процессом. Для отображения сообщения об ошибке требуется стек.

Рэймонд Чен недавно рассмотрел это.исключение, в этом случае процесс сохраняется, потому что он подключен в режиме отладки к процессу отладчика.Ваш процесс не отображает ошибку, отладчик.

На компьютерах с Windows вы можете перехватить исключение SEH, которое соответствует переполнению стека.Например, вы можете увидеть исходный код boost :: regex (Google для BOOST_REGEX_HAS_MS_STACK_GUARD).

2 голосов
/ 05 августа 2010

Вполне возможно, что компилятор оптимизировал предполагаемое переполнение стека. Рассмотрим следующий пример псевдокода:

void RecursiveMethod(int n)
{
    if (n % 1024 == 0)
        print n;

    // call recursively
    RecursiveMethod(n + 1);
} 

Метод будет вызывать себя рекурсивно и довольно быстро переполнять стек, потому что нет условия выхода.

Однако большинство компиляторов используют хвостовую рекурсию , метод, который переводит рекурсивный вызов функции в конструкцию цикла.

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

У Барта де Смета есть хорошая статья в блоге, где объясняется, как эта техника работает в .NET:

Случай неудачной демонстрации - StackOverflowException для x64

1 голос
/ 05 августа 2010

В отладочной сборке выполняется ряд проверок стека, чтобы помочь вам обнаружить такие проблемы, как переполнение стека, повреждение стека и т. Д. Их нет в сборках выпуска, поскольку они могут повлиять на производительность приложения.Как отмечали другие, переполнение стека является неопределенным поведением, поэтому компилятору вообще не требуется реализовывать такие проверки стека.

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

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

1 голос
/ 05 августа 2010

В режиме отладки вы хотите накладные расходы. Вы хотите, чтобы он обнаружил, сломали ли вы свой стек, переполнили ли вы буферы и т. Д. Эти издержки встроены в инструментарий отладки и отладчик. В терминах высокого уровня инструментарий отладки - это дополнительный код и данные, помещаемые туда, чтобы помочь помечать ошибки, а отладчик предназначен для обнаружения помеченных ошибок и уведомления пользователя (в дополнение, конечно, к отладке).

Если вы работаете с проектом, скомпилированным в режиме выпуска, или без отладчика, никто не услышит крик вашей программы, когда она умрет :) Если дерево падает в лес ...

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

...