Reputation: 6462
I think I might be asking a very wrong question, but I really tried to understand it by googling, but with no luck.
As we know, we have a stack and heap. Heap for the dynamically allocated ones, stack for local variables and e.t.c.
Let's say I have the following c++ code.
void bla(int v1, int v2, int v3) {
int g = v1 + v2+ v3;
}
void nice(int g){
int z = 20;
int k = 30;
bla(g, z, k);
}
int main(){
cout<<"Hello World";
nice(40);
}
Now, let's imagine there's a stack. I understand that for example values z,k,g
will be stored on stack. But when I call the function nice
which calls bla
where are those stored ? I've read that each function execution causes call stack size to increase by 1. I'd say that even creating local variables also causes call stack to be increased by 1.
So, how are those(callstack
, stack
) related at all ?
Here is my assumption:
When we call nice
, completely new stack
gets created. In there, we store z and k
. When nice
calls bla
, now another stack
gets created for bla
and this second stack stores v1,v2,v3,g
. and so on. each function needs its own callstack
,but we can call this stack
too.
Upvotes: 5
Views: 2848
Reputation: 76601
Stack denotes a data structure which consists of a set of usually similar items and has the following abilities:
Your memory has a section called "the stack", where, as you correctly understood, functions are stored. That is the call stack. However, stack and call stack are not 100% equivalent, since stacks are used in many other cases, basically whenever you need a LIFO (Last In First Out) processing. It's used at the LIFO policy of the CPU, for example, or, when you do a depth-first search in a graph. In short, stack is a data structure, which can be applied in many cases, the call stack in memory being a prominent example.
So, why stack is in use to store function calls in memory. Let's take into consideration embedded function calls, like:
f1(f2(...(fn(x))...))
It's a rule of thumb that in order to evaluate fi, 1 <= i < n, you need to evaluate fj, where 1 < j <= n, assuming that i < j. As a result, f1 is the first to be called, but the last to be evaluated. Hence, you have a LIFO processing, which is best done via using a stack.
Upvotes: 1
Reputation: 238361
So, how are those(callstack, stack) related at all ?
They are very much related. They are the same thing. It is also called the execution stack.
This "callstack" is not to be confused with the general concept of "stack" data structure. The callstack called a stack because that describes the structure of the callstack.
causes call stack size to increase by 1
By "1" sure, but what it the unit of the increase? When you call a function, the stack pointer is incremented one stack frame. And the size (measured in bytes) of the stack frame varies. The frame of a function is big enough to contain all local variables (the parameters may also be stored on the stack).
So, if you wish to measure the increment in bytes, then it is not 1, but some number greater than or equal to 0.
I'd say that even creating local variables also causes call stack to be increased by 1.
As I described, having a local variable affects how the stack pointer is incremented when the function is called.
When we call nice, completely new stack gets created.
No, the same stack is shared by all function calls in the entire thread of execution.
Pretty much none of this is specified by the C++ language, but rather are implementation details that apply to most C++ implementations in typical case, but are simplified for easier understanding.
Upvotes: 2
Reputation: 8945
Each running process is allocated a chunk of memory which it calls "the stack." And, this area of memory is used both to represent the "call/return sequence" (through what are known as "stack frames"), and the so-called "local variables" that are used by each routine that is called. They are one and the same.
Usually, different CPU registers are used to point simultaneously to each thing. One register points to the "local variable" values, while an entirely different register points to the "stack frame." (In interpreters, a similar mechanism is used.) There's also a third register which indicates the current "top of stack."
At the beginning of executing each new function, the "top of stack" is simply moved ahead to account for the local variables, after the "local variables pointer" remembers what it used to be.
When a "return from subroutine" occurs, the "top-of-stack pointer" is reverted to some previous value, and everything that once existed "above it" is now, literally, forgotten. Because it no longer matters.
Upvotes: 4