Относительно повторного использования стека функции, называя себя?

если бы вызовы функции самостоятельно при определении переменных одновременно это привело бы к переполнению стека? Есть ли любая опция в gcc для многократного использования того же стека.

void funcnew(void)
{
   int a=10;
   int b=20;
   funcnew();
   return ;
 }

действительно ли функция может снова использовать стековый фрейм, который она использовала ранее? Какова опция в gcc для многократного использования того же кадра в хвостовой рекурсии??

7
задан Ether 22 February 2010 в 05:16
поделиться

5 ответов

Да. См. раздел

-foptimize-silbling-calls

Оптимизация одноуровневых и конечных рекурсивных вызовов.

Включено на уровнях -O2, -O3, -Os.

Ваша функция компилируется в:

funcstack:
.LFB0:
    .cfi_startproc
    xorl    %eax, %eax
    jmp func
    .cfi_endproc

(обратите внимание на переход к func)

Повторное использование кадра стека при завершении функции вызовом - это включает в себя в своем полном обобщении манипулирование стеком, чтобы поместить параметры в правильное место и заменить вызов функции прыжком к началу функции - это хорошо известная оптимизация, называемая [i] удаление хвостового вызова [/i]. Это предписано некоторыми языками (например, схема) для рекурсивных вызовов (рекурсивный вызов является естественным способом выражения цикла в этих языках). Как указано выше, gcc имеет оптимизацию, реализованную для C, но я не уверен, какой другой компилятор имеет его, я бы не зависел от него для портативного кода. И обратите внимание, что я не знаю, какие ограничения на него есть - я не уверен, например, что gcc будет манипулировать стеком, если типы параметров различны.

-121--3977986-

По одному приложению для каждого экрана/ subdomain.heroku.com.

-121--2561257-

Да, в некоторых случаях компилятор может выполнить оптимизацию хвостового вызова . Необходимо ознакомиться с руководством компилятора. (AProgrammer, похоже, процитировал руководство GCC в своем ответе.)

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

0
ответ дан 7 December 2019 в 05:22
поделиться

Нет, каждая рекурсия - это новый кадр стека. Если рекурсия бесконечно глубока, тогда необходимый стек также бесконечен, поэтому вы получите переполнение стека.

0
ответ дан 7 December 2019 в 05:22
поделиться

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

0
ответ дан 7 December 2019 в 05:22
поделиться

Да. См.

-foptimize-sibling-calls

Оптимизация одноуровневых и хвостовых рекурсивных вызовов.

Включено на уровнях -O2, -O3, -Os.

Ваша функция скомпилирована в:

funcstack:
.LFB0:
    .cfi_startproc
    xorl    %eax, %eax
    jmp func
    .cfi_endproc

(обратите внимание на переход к функции)

Повторное использование кадра стека, когда функция завершается вызовом - это включает в себя в полной мере манипулирование стеком для помещения параметров в правильное место и замена вызова функции переходом к началу функции - это хорошо известная оптимизация под названием [i] удаление хвостового вызова [/ i].Некоторые языки (например, схема) требуют его для рекурсивных вызовов (рекурсивный вызов - это естественный способ выразить цикл на этих языках). Как указано выше, в gcc реализована оптимизация для C, но я не уверен, в каком другом компиляторе она есть, я бы не зависел от нее для переносимого кода. И обратите внимание, что я не знаю, какие ограничения есть на это - я не уверен, например, что gcc будет манипулировать стеком, если типы параметров разные.

5
ответ дан 7 December 2019 в 05:22
поделиться

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

Возможно (я узнал об этом недавно) возможно, что компилятор оптимизирует ваш цикл до хвостовой рекурсии (что заставляет стек вообще не расти). Ссылка на вопрос о хвостовой рекурсии в SO

3
ответ дан 7 December 2019 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: