main() calling f1(), f1() calling f2(), f2 calling f3(), f3() calling f4() and so on...
A function calls another function and chain goes on.
| |
| f4() |
| f3() |
| f2() |
| f1() |
| main() |
__________
When a function is called a structure named Activation record is prepared that contains the information associated with it's call. That activation record regarding each function is pushed on to a stack called program-stack or run-time-stack . I have no good idea either about the Activation record or Run-time-stack . My problem is :
A function calls another function and chain goes on. But for how long? how long this nested calls can go on? And What do they depend on? Is it OS or bit architecture of the machine ?
What does Activation Record contain? What is its structure like? Is local data also passed to this?
What parameters are set for stack overflow of such type of functions(which have several nested calls or recursive functions) ? I mean how to know in advance to avoid overflow .
An "activation record" is an abstract concept, useful for academics performing formal analysis of algorithms and not too concerned by the actual implementation.
Real systems have function arguments, local variables, saved register values, return addresses, etc. Some systems use CPU registers for some of all of this information.
As the stack pointer is often one of the registers saved, in many environments one can "walk" the stack by using a frame pointer register to locate the saved value of the stack pointer and frame pointer as it existed in the caller, repeating as necessary. If a compiler setting such as "frame pointer omission" is activated (or the system doesn't use a frame pointer register), this can instead be done using the stack pointer combined with debug metadata.
If you're writing such a stack walking algorithm, or computing total stack usage, you need to be concerned with stack layout. It also is useful in understanding how a buffer overflow in a stack variable can lead to overwriting the return address in a "return to libc" exploit.
But for most purposes, like explaining how recursive functions have multiple instances of local variables, or lifetime of aliases (pointers and references) to local variables, the conceptual model of a stack of activation records is sufficient.
If your function creates local variables on the stack you will see the address of that variable change as the stack gets deeper. You could get a rough idea of how much of the stack you have used up by keeping track of that number as it changes. Do this for your education - not in actual code. Something like this:
#include <stdio.h>
int foo(void);
char *sp;
int main(void){
char a;
sp = &a;
foo();
return 0;
}
int foo(void) {
char c;
long depth;
depth = sp - &c;
if(depth < 1000) {
printf("depth is %ld\n", depth);
foo();
}
return 0;
}
On my machine it seems that the stack grows by 48 bytes for each subsequent call to foo()
.
"Activation record" is synonymous with "stack frame" - I had to look this up as I'm not familiar with that term.
function beginFoo() {
foo(0);
}
function foo(int depth) {
if( depth > 10 ) return; // avert possible stack-overflow
foo(depth + 1);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.