M
M
martuwka2017-01-04 03:04:56
Programming
martuwka, 2017-01-04 03:04:56

What is a call stack?

When debugging a program in Microsoft Visual Studio, I came across such a field as Call Stack. Can someone explain in a little more detail what it is, why it is and how to use it. I don't know English very well, so I didn't search on English-language sites. Maybe someone with experience will explain or give a link to read about it (only in Russian), I will be grateful.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
M
Maxim Moseychuk, 2017-01-04
@martuwka

Part of the computer's memory is dedicated to the stack.
When you call a function in your code, the function's parameters are pushed onto the stack (often, but there are other ways). It is also necessary to know where to return from the function - the return address is put on the stack.
Call Stack - a window that displays all nesting levels of function calls.
Там вы можете узнать, в какой функции вы сейчас находитесь, из какой функции она была вызвана и так далее рекурсивно наверх вплоть до точки входа в программу.
Собственно call stack вычисляется на основе информации из стека.

S
Saboteur, 2017-01-04
@saboteur_kiev

Once upon a time there was a goto statement and programs looked like this

10 let a = 5
20 if a =5 then goto 100
30 print "Вот и все, ребята"
40 exit

100 print "Да, наше a = 5"
110 goto 30

We check something, if the check is successful, we call some action. Then we return back.
But this option turned out to be inconvenient if this kind of action needs to be called from different places, and then return to these different places. Therefore, now not goto is used, but call (call), which puts on the stack the address of the current place of execution and goes to the subroutine. At the end of the subroutine on the return command, it takes the address from the stack and returns back to it.
Since you can put something else on the stack, you can call another subroutine inside the called subroutine, and recursively call as many times as you need. Then all calls will be beautifully closed by return-ami in the reverse order.
main () {
  call program1;
  call program2;
}

program1 () {
call program 3;
return;
}

program2 () {
call program3;
return;
}

program3 () {
return;
}

In this version, it works for us like this:
1. from the main part, program1 is called (the address of this one is put on the stack)
2. from the called program1, program3 is called (the address of this command is added to the stack, there are already two)
3. from program3 we return, taking the last value from the stack (back to program1)
4. returning again, taking the address from the stack and hitting main
5. the same with the call to program2-program3-program2-main
The stack usually grows from top to bottom, each return command takes the most recent bottom address and returns on it, which allows you to create many nested calls, and work with them recursively.
But we must not forget that the stack is not infinite. ten or a hundred calls are nothing at all on modern computers, but a million or a billion, times the size of the address (eg 4 bytes), can take megabytes and gigabytes.

R
Rou1997, 2017-01-04
@Rou1997

So that when execution stops (at a breakpoint or when an exception is thrown), find out in which function (and possibly with the number of the line of code) the stop occurred, with nesting.
Example:

void foo2() {
foo3(5 / 0);
}

void foo1() {
foo2();
}

void main() {
foo1();
}

Call stack trace of exception:
foo2
foo1
main

And here is English, you just had to check this window in operation.

M
Mercury13, 2017-01-05
@Mercury13

Call stack is a call stack, a hardware feature of all large processors.

int foo()
{
   int y = ...;
   if (y < 0)
     y = -y;
   return y;
}

void bar()
{
   int x = foo();
   if (x != 0)
      bar();
   foo();
}

void main()
{
  int z = foo();
  bar();
}

Here we go to the main() function. At this time, the variable z appears in memory. And then in foo(), the y variable also appears. And then we exit foo - y disappears. What do we get? Either we add one or more local variables to the end, or delete them from the same end. What data structure is suitable for this? Stack: add to end, remove from end. All this, I remind you, is implemented in x86 hardware, with one segment, two registers (esp = 32-bit stack pointer and ebp = 32-bit base pointer) and several commands (push, pop, call, ret ...).
Local variables belonging to a single function are called a stack frame. At the same time, there can be several frames of one function if it calls itself, directly or indirectly - like the bar() function.
In the most famous calling model, you can "unwind" the stack frame by frame to see which function called which. This is displayed in the Call Stack window. Since debug access is very slow, usually only the top of the stack is displayed. Moreover, by clicking anywhere in the Call Stack window, we can see the local variables of that function instance .
Because the stack is hardware, it cannot be extended; you can only specify before the start of the program / thread how much memory is enough for us. This is why the “stack overflow” error is common.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question