6

I ran this program and it output

...

65088
65089
65090

and then it stopped. Windows 7 said a.exe stopped working. Here is the code:

#include <stdio.h>

void go(void);

main()
{
    go();
}

void go(void)
{
    static int i = 0;
    printf("%d\n", i++);
    go();
}

I think this program should keep on printing numbers indefinitely due to recursion, but it stops at 65090! The C code is compiled with gcc. Any ideas?

sigjuice
  • 28,661
  • 12
  • 68
  • 93
functionptr
  • 317
  • 4
  • 10

9 Answers9

14

You are going to overflow the stack at some point because each call to go() must push a return address on the stack even though you pass no arguments to the function call. So every call to go() is taking up a pointer-sized block on the stack for that return address. Since the stack has a limited size, that means at some point you're going to run out of space. The C-language does not specify that a tail-call optimization should take place for circumstances like this, although some compilers (like gcc) do offer that option via optimization switches. But that would be something that is compiler-specific, and independent of the language specification.

Jason
  • 31,834
  • 7
  • 59
  • 78
10

It stops because it is overflowing the stack. Once you overflow the stack the results are undefined.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • the msvc compiler might do tail call optimization on this code if it's compiled with opimization (and thus not crash) – nos Jun 24 '11 at 20:18
  • 1
    A way you can achieve an infinite print like what you want would need to be done with a loop in main, not recursion, like: `while(true) { go(); }` , removing the recursion from the function itself of course – Dan F Jun 24 '11 at 20:19
  • @nos Yes, optimizations can hide a problem such as this one; but check out what happened here: http://stackoverflow.com/questions/6386601/given-that-b-is-always-non-zero-why-b-b-b-works-but-b-does-not/6386896 – cnicutar Jun 24 '11 at 20:20
7

You cannot recurse infinitely on a machine with finite resources -- specifically, the stack. Each nested subroutine call required more stack space, and eventually you will run out.

mah
  • 39,056
  • 9
  • 76
  • 93
  • 1
    Actually, one can with tail-call optimization... (granted, a feature not generally present in C, but the function *is* TCO'able). –  Jun 24 '11 at 20:18
  • That is a compiler-specific optimization, not a language standard. So in order to get that type of functionality, you would have to provide the correct settings to your compiler, if it's supported. – Jason Jun 24 '11 at 20:20
  • @Jason Of course. C says nothing about it. I was simply challenging the assertion that "you cannot recurse infinitely on a machine with finite resources" ;-) –  Jun 24 '11 at 20:22
2

By "stopped working" do you mean crashed? That would make sense. Every program has a limited stack depth, and each level of recursion (i.e. each new function called) sets up itself on the stack. So if your program reached the maximum stack depth, it will crash!

Dan Fego
  • 13,644
  • 6
  • 48
  • 59
2

It appears your compiler does not perform any tail call optimizations. Even though there is no reason for the runtime system to maintain a stack of calls, it does so any way.

sarnold
  • 102,305
  • 22
  • 181
  • 238
  • +1 ... just for the link. (The other answers are lacking in external resources :-/) –  Jun 24 '11 at 20:25
1

The recursion depth is limited by the program stack size. Each call pushes additional info to the stack, and when the stack is exhausted - it overflows. In your case you got 65090 frames in the stack before overflowing, once overflown- your program is dead.

littleadv
  • 20,100
  • 2
  • 36
  • 50
1

I think you've run out of space on your stack. Your program is only allowed a certain amount of memory (which your dev environment can probably change), and because go() is called within itself, 65000 copies of the function call exist at the same time.

Luke
  • 7,110
  • 6
  • 45
  • 74
1

First of all, it's not C that limits the recursion. It's your Operating System!

This happens because recursion uses the stack. Do you know what the stack is? It's a memory region of the application that is used to store (local) variables, or parameters that must be send from one function to another during a function call. It also stores other informations, like the address of the function it must return to after executing the current one.

Now, you see, infinite recursion is a problem because more data is being stored on the stack after each recursion, and since these functions never return, their resources on stack are also never deallocated. At some point, the stack is going to run out of memory and it's going to explode in your face.

On Windows, if you need to increase the stack size you could try this.

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
0

Regardless of whether this does recursion or not, once you reach INTMAX your program may do what it pleases since overflow of int is undefined behavior. And since a static analysis can show this, your whole program may do what pleases.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177