call stack
When you make a function call, the computer saves on the stack (on the top, of course)
four things, which are listed here. Note that this process is true for all function calls, not
just those that are recursive:
1. (still in your function) The parameters you are passing to the function.
2. (as it travels to the other function) The code location to return to when the called
function is completed.
3. (inside the called function) Your “base pointer” so that it will be able to restore it
when it is done. It then sets the base pointer to the current stack location, for its
own use. The base pointer is how it finds both the parameters you passed in and
the local variables for which it is about to allocate space on the stack.
4. (inside the called function) Space for any local variables the function needs.
Of course, your function went through these same steps when it was called. In your function,
every time you access one of the parameters you passed in or one of the automatic
variables you declared as local to your function, the function pulls these values out of
memory at a location defined by the base pointer—plus or minus some known amount.
When a function returns, it undoes all these steps, in reverse order: The function deallocates
the space for local variables, restores the base pointer of the caller, and returns to
the code address saved (popping that address off the stack at the same time). Finally, the
function deallocates the space for the parameters that were passed in.
When a function calls itself, this process doesn’t change. In fact, the compiler does not
even know the difference. But we can see that this process supports the effect we want.
Each time our recursive function calls itself, new copies of the parameters are saved on
the stack, the return address is saved if we are in the middle of evaluating an expression
(as in the Fibonacci function), and the new recursion allocates its own space for all the
local variables. In the function Directory::Display(), for example, the variable
newPrefix is allocated fresh each time the function is called. This arrangement does not
interfere with other versions of that variable that are still alive inside earlier recursions of
the function.
Now we can consider the effects of infinite recursion—that is, recursion for which the
author did not properly confirm the termination requirements. Every time you recurse,
some amount of stack space is used. Even if you created a recursive function with no
parameters and no local variables, you cannot get around the need to save the base pointer
and the return address. If your function never stops recursing, it will grow the stack
until the memory allocated for the stack is used up. Typically, the stack space is adjacent
to the global memory that will be tromped on in the computer’s desperate attempt to save
base pointers and return addresses. Eventually, your computer will write over something
critical or it will have a memory fault. In either case, your program will halt (or maybe
your whole computer will halt). Because this is rarely the desired result, you should
check your termination requirements carefully.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.