views:

162

answers:

4

Recently I made a program in c, which only purpose was to overflow the stack, using a recursive method. Apparently there is no portable way(like a try / catch block, at least in c), to avoid that the next call to a function causes a stack overflow. My question is, in your opinion, high-level languages should offer alternatives on resizing the stack, maybe a flag on the compiler, or these applications must be built with low-level languages.

+1  A: 

The size of the stack is normally set by the build tools you use to create your application, such as the compiler and the linker. The means to do this are always platform specific and so cannot be performed by standardised high-level languages, or standardised low-level languages, for that matter.

anon
Also, for a compiled language different platforms require different amounts of stack to do the same thing. Sometimes massively different. So a programmer cannot know that (say) 10k of stack is sufficient on any platform. The compiler can't work it out either, because calculating depth of recursion is a halting problem. So even on languages/frameworks where you can specify the stack size in a standard way (and I've seen some), that feature isn't as useful as you might hope.
Steve Jessop
+2  A: 

Usually I think it is probably not a good idea to be flirting with the limits of the computer or operating system. If you find yourself overflowing the stack, running out of memory, running out of open file handles and that kind of thing, it is wise to redesign your program, rather than wonder about how the limitations can be avoided.

1800 INFORMATION
+2  A: 

Generally it's the job of the loader (the thing that loads your EXEs, fixes up references to shared libraries, relocates code, etc) to set up the memory areas, but it usually does so in response to fields in the header executable that were put there by the linker.

But this sort of thing is not covered by any standard, it's an OS-level thing.

paxdiablo
+1  A: 

Apparently there is no portable way(like a try / catch block, at least in c), to avoid that the next call to a function causes a stack overflow.

That's to support platforms which cannot extend stack dynamically, and also don't check at runtime on each call that the stack is still in bounds. Any sort of checking (unless done by the hardware) would slow down the vast majority of code which never goes anywhere near the end of the stack, so is not really in the spirit of C or C++.

So recursing too deep is a hardware exception (or memory corruption). C and C++ do not try to specify what happens on a hardware exception: they are outside the scope of the languages and undefined behaviour, so there is no portable way to recover.

In contrast, Java throws StackOverflowError when you recurse too deep. Although not recommended, it is possible to catch this.

I haven't seen a language with an isThereEnoughStackFor primitive, which would let you write:

if (isThereEnoughStackFor(foo)) {
    foo(12);
} else {
    printf("error - no stack\n"); // I hope there's enough stack for printf
}

For any such scheme to work, you would need to know how much stack foo requires. This depends on foo, but also potentially on everything foo calls, and hence on its parameters. So foo and all its dependencies would either need to report how much stack they require (in which case how do you know there's enough stack to compute it?), or else would need to do similar checks before calling anything (in which case you'd have a limited menu of functions you're "allowed" to call, like in signal handlers).

Once you have runtime polymorphism (in C, consider if foo is a function pointer rather than a function name), checking stack by any means other than built-in tests on every call has proven to be either impossible or not worth the effort.

Steve Jessop