Lists: The Call Stack

    Lists: The Call Stack

      When you run a program in any language, whether it's Java, C, Python or Lisp, the computer automatically creates a stack of all the functions currently running. This is called—wait for it—the call stack. This stack also saves space, called the stack frame for any variables that function might use. When the function finishes running and returns to the calling function, the stack frame for that function is deleted and the function gets popped from the call stack.

      Here's an example program in C (minus all those pesky function definitions) that creates an army of kittens for all your guerilla cuddling needs.

      main(){
      	int kittens = 9;
      	int success = kittenAttack (kittens);
      }
      	
      int kittenAttack(int kittens){
      	int cute = 4;
      	while(kittens > 0){
      		kitten(cute);
      		kittens--;
      	/*other implementation not shown*/
      }
      	
      void kitten(int cutenessFactor){
      	int paws = 4;
      	/*other implementation not shown*/
      }

      This program has three functions:

      • main()
      • kittenAttack()
      • kitten()

      main() calls kittenAttack(), which takes one argument: the number of battle-ready kittens you'll need to stage your cuddle battle. kittenAttack() returns an integer to main(): 1 if it was successful (and your army of kittens is ready) and 0 if it failed (probably because all the kittens were too busy napping).

      kittenAttack() also calls kitten(), a function that takes one argument: how cute the kitten is. kitten() has one local variable in that function: the number of paws the kitten should have.

      When this method runs, its call stack is going to add one function at a time as it's called. Since most programming languages start with a main() function, that's going to be added to the stack first.


       

      As main() runs, it's going to make space for kittens in the stack frame and push kittens() onto the stack.


       

      Then, before kittenAttack() itself runs, its return value gets pushed. The computer does that because main() receives that value back from kittenAttack() as it pops the function from the list. The final thing that always gets added to a stack frame is the return statement. Then it can dig down into the called function.

       

      When kittenAttack() gets called, it'll be pushed to the top of the stack starting its very own own stack frame, along with its parameter cute.

      Fancy.

      Once kittenAttack() is nicely nestled in that call stack, the computer's going to add kitten() on, leaving space for its own stack frame.


       

      And finally paws gets its own place in the stack frame.


       

      Once each function completes, it's going to be popped off the stack, along with its stack frame. If a function returns something, the return slot of the previous function gets that something, whatever it is.

      In the example, kitten() will complete first. Since it doesn't return anything, nothing else happens, it'll just pop off the stack cleanly.


       

      Then kittenAttack() completes and returns 1 for success. Since the implementation isn't technically shown, you'll just have to trust us on that one, but you can assume the 16th Kittie Division was successfully formed. The kittenAttack() stack frame is removed, but main's return slot now has a 1 in it.


       

      At long last, main() ends this very important function of creating an indeterminate number of kittens to do our bidding and the program finishes, leaving an empty call stack.

      In the totally uncommon event of an error disrupting the code, most programming languages will let you print a stack trace (a list of the functions and frames on the call stack) to figure out which function took it down. You can pretty much trust that if something went wrong, the call stack has to have something in it, since the program didn't finish normally.

      And that's it. That's all we have to stack on you.

      (Source)