В чем разница между следующими двумя кодами?
int main()
{
printf("hello\n");
main();
}
А также
int main()
{
while(1)
printf("hello\n");
return 0;
}
Первый помещается в стек каждый раз, в то время как выделение стека для второго выполняется только один раз. Есть что-нибудь, связанное с переполнением памяти в while infinite loop
?
7 ответов
Вы должны заметить, что спецификация C фактически ничего не упоминает о «стеке». Использование стека - это всего лишь деталь реализации, и разработчики компиляторов / программисты могут использовать любой другой метод для реализации вызовов функций и хранения локальных переменных. Однако какой бы метод ни использовался, он в конечном итоге израсходует некоторый ресурс (например, память), и, как и все остальное, ресурсы на компьютере ограничены, поэтому их использование рано или поздно вызовет некоторую ситуацию переполнения.
С другой стороны, пустой while
цикл фактически не использует никаких дополнительных ресурсов, независимо от того, сколько итераций он выполняет. В вашем случае это более сложно, потому что вы не знаете, что делает printf
, какие ресурсы он использует, или какие ресурсы используются слоями ниже вызова printf
, поэтому здесь может быть ограничение. Например, что, если окно терминала настроено на использование «бесконечной» прокрутки, тогда эта прокрутка будет расширяться до тех пор, пока не займет всю доступную память.
Цикл будет выполняться вечно, а рекурсивный код в конечном итоге вызовет переполнение стека, когда буфер стека будет заполнен.
Если у вас есть выбор между рекурсивной функцией и итеративной функцией, вам следует предпочесть итеративную функцию, поскольку рекурсивный код может привести к переполнению стека и другим проблемам. Кроме того, он потребляет память (в стеке), в то время как цикл не выделяет больше памяти при каждом запуске.
Бесконечная рекурсия - всегда ужасная идея. Не делай этого.
Вы во власти своего компилятора. Если он оптимизирует его до бесконечного цикла, вам повезло. В противном случае у вас закончится место в стеке, и ваше приложение (скорее всего) выйдет из строя.
Бесконечная рекурсия вызовет некрасивый Segmentation Fault
, второй будет работать навсегда .
Первый, скорее всего, вызовет переполнение стека, а второй потенциально будет работать вечно.
Основное очевидное отличие состоит в том, что первый пример обязательно приведет к переполнению стека, а второй - нет.
Это связано с тем, что в первом случае каждый раз, когда вызывается main (), адрес возврата помещается в стек перед переходом к началу функции main (). Эти адреса возврата никогда не извлекаются из стека, поскольку функция никогда не возвращается.
В бесконечном цикле это не так, и снова и снова вызывается и возвращается только функция printf (), что не приведет к изменению указателя стека.
Как уже отмечалось, рекурсивный метод потребляет стек, и в конечном итоге у вас закончится место в стеке.
Похожие вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.