The Stack Frame
- Manually trace the flow of control in the above program, and fill in the stack
frames at each call statement. For each return address, use the line number to which
it will go back. - Compile the program for real, and run it under the debugger. Look at the additions
to the stack when a function has been called. Compare with your desk checked
results to work out exactly what a stack frame looks like on your system.
Remember that compiler-writers will try to place as much of an activation record in
registers as possible (because it's faster), so some of this may not be visible on the stack.
Refer to the frame.h file to see the layout of a stack frame.
The auto and static keywords
The description of how the stack implements function calling also explains why it doesn't work to
return a pointer to a local automatic variable from a function, like this:
char * favorite_fruit () {
char deciduous [] = "apple";
return deciduous;
}
The automatic variable deciduous is allocated on the stack when the function is entered; after the
function is exited, the variable no longer exists, and the stack space can be overwritten at any time.
Pointers that have lost their validity in this way (by referencing something that is no longer live) are
known as "dangling pointers"—they don't reference anything useful, just kind of dangle in space. If
you need to return a pointer to something defined in a function, then define the thing as static.
This will ensure that space for the variable is allocated in the data segment instead of on the stack. The
lifetime of the variable is thus the lifetime of the program, and as a side effect it retains its value even
after the function that defines it exits. That value will still be available when the function is next
entered.
The storage class specifier auto is never needed. It is mostly meaningful to a compiler-writer
making an entry in a symbol table—it says "this storage is automatically allocated on entering the
block" (as opposed to statically allocated at compiletime, or dynamically allocated on the heap). Auto
is pretty much meaningless to all other programmers, since it can only be used inside a function, but
data declarations in a function have this attribute by default. The only use we have ever found for the