It seems that I get the idea of call stack in programming language design. But I cannot find (probably, I just don't search hard enough) any decent explanation of what stack frame is.
So I would like to ask someone to explain it to me in a few words.
A stack frame is a frame of data that gets pushed onto the stack. In the case of a call stack, a stack frame would represent a function call and its argument data.
If I remember correctly, the function return address is pushed onto the stack first, then the arguments and space for local variables. Together, they make the "frame," although this is likely architecture-dependent. The processor knows how many bytes are in each frame and moves the stack pointer accordingly as frames are pushed and popped off the stack.
EDIT:
There is a big difference between higher-level call stacks and the processor's call stack.
When we talk about a processor's call stack, we are talking about working with addresses and values at the byte/word level in assembly or machine code. There are "call stacks" when talking about higher-level languages, but they are a debugging/runtime tool managed by the runtime environment so that you can log what went wrong with your program (at a high level). At this level, things like line numbers and method and class names are often known. By the time the processor gets the code, it has absolutely no concept of these things.
If you understand stack very well then you will understand how memory works in program and if you understand how memory works in program you will understand how function store in program and if you understand how function store in program you will understand how recursive function works and if you understand how recursive function works you will understand how compiler works and if you understand how compiler works your mind will works as compiler and you will debug any program very easily
Let me explain how stack works:
First you have to know how functions are represented in stack :
Heap stores dynamically allocated values. Stack stores automatic allocation and deletion values.
https://i.stack.imgur.com/P56ru.jpg
Let's understand with example :
def hello(x):
if x==1:
return "op"
else:
u=1
e=12
s=hello(x-1)
e+=1
print(s)
print(x)
u+=1
return e
hello(4)
Now understand parts of this program :
https://i.stack.imgur.com/Mu9nS.png
Now let's see what is stack and what are stack parts:
https://i.stack.imgur.com/1PI03.png
Allocation of the stack :
Remember one thing: if any function's return condition gets satisfied, no matter it has loaded the local variables or not, it will immediately return from stack with it's stack frame. It means that whenever any recursive function get base condition satisfied and we put a return after base condition, the base condition will not wait to load local variables which are located in the “else” part of program. It will immediately return the current frame from the stack following which the next frame is now in the activation record.
See this in practice:
https://i.stack.imgur.com/N94IW.png
Deallocation of the block:
So now whenever a function encounters return statement, it delete the current frame from the stack.
While returning from the stack, values will returned in reverse of the original order in which they were allocated in stack.
https://i.stack.imgur.com/5TrkZ.png
hello()
has recursively called hello()
which has then (again) recursively called hello()
, and the global frame is original function which called the first hello()
?
A quick wrap up. Maybe someone has a better explanation.
A call stack is composed of 1 or many several stack frames. Each stack frame corresponds to a call to a function or procedure which has not yet terminated with a return.
To use a stack frame, a thread keeps two pointers, one is called the Stack Pointer (SP), and the other is called the Frame Pointer (FP). SP always points to the "top" of the stack, and FP always points to the "top" of the frame. Additionally, the thread also maintains a program counter (PC) which points to the next instruction to be executed.
The following are stored on the stack:
local variables and temporaries;
actual parameters of the current instruction (procedure, function, etc.).
There are different calling conventions regarding the cleaning of the stack.
"A call stack is composed of stack frames..." — Wikipedia
A stack frame is a thing that you put on the stack. They are data structures that contain information about subroutines to call.
Programmers may have questions about stack frames not in a broad term (that it is a singe entity in the stack that serves just one function call and keeps return address, arguments and local variables) but in a narrow sense – when the term stack frames
is mentioned in context of compiler options.
Whether the author of the question has meant it or not, but the concept of a stack frame from the aspect of compiler options is a very important issue, not covered by the other replies here.
For example, Microsoft Visual Studio 2015 C/C++ compiler has the following option related to stack frames
:
/Oy (Frame-Pointer Omission)
GCC have the following:
-fomit-frame-pointer (Don't keep the frame pointer in a register for functions that don't need one. This avoids the instructions to save, set up and restore frame pointers; it also makes an extra register available in many functions)
Intel C++ Compiler have the following:
-fomit-frame-pointer (Determines whether EBP is used as a general-purpose register in optimizations)
which has the following alias:
/Oy
Delphi has the following command-line option:
-$W+ (Generate Stack Frames)
In that specific sense, from the compiler’s perspective, a stack frame is just the entry and exit code for the routine, that pushes an anchor to the stack – that can also be used for debugging and for exception handling. Debugging tools may scan the stack data and use these anchors for backtracing, while locating call sites
in the stack, i.e. to display names of the functions in the order they have been called hierarchically. For Intel architecture, it is push ebp; mov ebp, esp
or enter
for entry and mov esp, ebp; pop ebp
or leave
for exit.
That’s why it is very important to understand for a programmer what a stack frame is in when it comes to compiler options – because the compiler can control whether to generate this code or not.
In some cases, the stack frame (entry and exit code for the routine) can be omitted by the compiler, and the variables will directly be accessed via the stack pointer (SP/ESP/RSP) rather than the convenient base pointer (BP/ESP/RSP). Conditions for omission of the stack frame, for example:
the function is a leaf function (i.e. an end-entity that doesn’t call other functions);
there are no try/finally or try/except or similar constructs, i.e. no exceptions are used;
no routines are called with outgoing parameters on the stack;
the function has no parameters;
the function has no inline assembly code;
etc...
Omitting stack frames (entry and exit code for the routine) can make code smaller and faster, but it may also negatively affect the debuggers’ ability to backtrace the data in the stack and to display it to the programmer. These are the compiler options that determine under which conditions a function should have the entry and exit code, for example: (a) always, (b) never, (c) when needed (specifying the conditions).
Stack frame is the packed information related to a function call. This information generally includes arguments passed to th function, local variables and where to return upon terminating. Activation record is another name for a stack frame. The layout of the stack frame is determined in the ABI by the manufacturer and every compiler supporting the ISA must conform to this standard, however layout scheme can be compiler dependent. Generally stack frame size is not limited but there is a concept called "red/protected zone" to allow system calls...etc to execute without interfering with a stack frame.
There is always a SP but on some ABIs (ARM's and PowerPC's for example) FP is optional. Arguments that needed to be placed onto the stack can be offsetted using the SP only. Whether a stack frame is generated for a function call or not depends on the type and number of arguments, local variables and how local variables are accessed generally. On most ISAs, first, registers are used and if there are more arguments than registers dedicated to pass arguments these are placed onto the stack (For example x86 ABI has 6 registers to pass integer arguments). Hence, sometimes, some functions do not need a stack frame to be placed on the stack, just the return address is pushed onto the stack.
Success story sharing