Question

Let me start by saying my question is not about stack overflows but on way to make it happen, without compile-time errors\warnings. I know (first hand) you can overflow a stack with recursion:

void endlessRecursion()
{
    int x = 1;
    if(x) endlessRecursion(); //the 'if' is just to hush the compiler
}

My question is, is it possible to overflow the stack by declaring too many local variables. The obvious way is just declare a huge array like so:

void myStackOverflow()
{
    char maxedArrSize[0x3FFFFFFF];  // < 1GB, compiler didn't yell
} 

In practice even 0xFFFFF bytes causes stack overflow on my machine

So, I was wondering:

  1. Since I haven't tried it, if I declare enough variables would the stack overflow?
  2. Is there a way to use the preprocessor or other compile-time "tools" (like C++ template meta-programming) to do the first thing, i.e. make it declare a lot of local variables, by somehow causing it to loop? if so, how?
  3. This is theoretical - Is there a way to know if the a program's stack would overflow at compilation time? and if so, please explain.
Was it helpful?

Solution

Yes, allocating a large amount of memory will cause a stack overflow. It shouldn't matter whether you allocate one large variable or a lot of small ones; the total size is what's relevant.

You can't do a compile-time loop with the preprocessor, but you can implement some shortcuts that let you generate large amounts of code without typing it all. For example:

#define DECLARE1 { int i;
#define END1 }

#define DECLARE2 DECLARE1 DECLARE1
#define END2 END1 END1

#define DECLARE4 DECLARE2 DECLARE2
#define END4 END2 END2

and so on. This puts the multiple int i; declarations in nested blocks, ensuring that all the objects exist at the same time while avoiding name conflicts. (I couldn't think of a way to give all the variables distinct names.)

DECLARE4 END4

expands to:

{ int i; { int i; { int i; { int i; } } } }

This won't work if your compiler imposes a limit on the length of a line after preprocessing.

The lesson here is that the preprocessor isn't really designed for this kind of thing. It's much easier and more flexible to write a program in your favorite scripting language that generates the declarations. For example, in bash:

for i in {1..100} ; do
    echo "    int i$i;"
done

OTHER TIPS

On question 3, I believe the answer is no. The compiler can know how much stack space each function uses. But the total stack space depends on your call sequences, which depend on logic evaluated at runtime. As long as there are no recursive calls, it seems possible to determine an upper bound for the stack space used. If that upper bound is smaller than the available stack space, you could be certain that the stack will not overflow. A lower bound seems possible as well. If that is higher than the stack size, you could be certain that the stack will overflow.

Except for very trivial programs, this would only give you boundaries, not an exact amount of stack space. And once recursion gets involved, I don't think there's an upper bound that you can statically determine in the general case. That almost starts sounding like the halting problem.

All of the very limited options above obviously assume that you have a given stack size. As other posters mentioned, the compiler can generally not know the stack size, because it's often part of the system configuration.

The closest I have seen are static analyzers. I seem to remember that some of them flag large stack variables. But I doubt that they try to analyze actual stack usage. It's probably just a simple heuristic that basically tells you that having large variables on the stack is a bad idea, and that you may want to avoid it.

Yes, too many variables will blow the stack.

Since I haven't tried it, if I declare enough variables would the stack overflow?

Yes, declaring a single array of large size and declaring multiple variables in same scope is similar.

Is there a way to use the preprocessor to do the first thing, i.e. make it declare a lot of local variables, by somehow causing it to loop?

I don't think so, as your compilation (and memory allocation) starts from main(). Whatever you declare using preprocessor commands is expanded in preprocessing stage. This stage doesn't involve any memory allocation.

This is theoretical - Is there a way to know if the a program's stack would overflow?

Yes, for linux system you can get the amount of stack memory allocated to your program, anything more than that will lead to stack Overflow. You can read the this link for details as how to know stack size of any process.

As to #3
Is there a way to know if the a program's stack would overflow at compilation time?

Yes. This is a standard feature of some PIC compilers for embedded processors especially those using a Harvard architecture But it comes at a cost: no recursion nor VLAs. Thus at compile time, an analysis of the code reports the maximum depth in the main processor code as well as the max depth handling interrupts. But the analysis does not prove that the maximum combined depth of those two will occur.

Depending on processor type, an ample stack can be allocated at compile time preventing possible overflow.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top