I have a rather huge recursive function (also, I write in C), and while I have no doubt that the scenario where stack overflow happens is extremely unlikely, it is still possible. What I wonder is whether you can detect if stack is going to get overflown within a few iterations, so you can do an emergency stop without crashing the program.
-
I don't think there is a portable solution, but if you don't care about portability, you could check the value of the stack pointer using inline assembly and do the emergency exit if the stack poinnter is smaller than a certain value. – Jabberwocky Feb 05 '16 at 11:39
-
You could also simply limit the recursion depth to a maximum depth. – Jabberwocky Feb 05 '16 at 11:41
-
2Not quite a duplicate, but related: http://stackoverflow.com/questions/199747/how-to-detect-possible-potential-stack-overflow-problems-in-a-c-c-program?rq=1 – Klas Lindbäck Feb 05 '16 at 11:41
-
1The best solution is always to get rid of the recursion when possible. Recursion should only be used as the very last resort to solve a problem. – Lundin Feb 05 '16 at 11:57
4 Answers
In the C programming language itself, that is not possible. In general, you can't know easily that you ran out of stack before running out. I recommend you to instead place a configurable hard limit on the recursion depth in your implementation, so you can simply abort when the depth is exceeded. You could also rewrite your algorithm to use an auxillary data structure instead of using the stack through recursion, this gives you greater flexibility to detect an out-of-memory condition; malloc()
tells you when it fails.
However, you can get something similar with a procedure like this on UNIX-like systems:
- Use
setrlimit
to set a soft stack limit lower than the hard stack limit - Establish signal handlers for both
SIGSEGV
andSIGBUS
to get notified of stack overflows. Some operating systems produceSIGSEGV
for these, othersSIGBUS
. - If you get such a signal and determine that it comes from a stack overflow, raise the soft stack limit with
setrlimit
and set a global variable to identify that this occured. Make the variablevolatile
so the optimizer doesn't foil your plains. - In your code, at each recursion step, check if this variable is set. If it is, abort.
This may not work everywhere and required platform specific code to find out that the signal came from a stack overflow. Not all systems (notably, early 68000 systems) can continue normal processing after getting a SIGSEGV
or SIGBUS
.
A similar approach was used by the Bourne shell for memory allocation.

- 88,405
- 25
- 200
- 352
-
Yeah, similar hacks are posible in Windows, though it's much easier if you use a language that supports exceptions and can catch a Windows structured stack overflow exception. – Martin James Feb 05 '16 at 11:50
-
@MartinJames The solution is non-portable anyway, so on Windows just use whatever Windows API solves the problem. – fuz Feb 05 '16 at 11:52
Heres a simple solution that works for win-32. Actually resembles what Wossname already posted but less icky :)
unsigned int get_stack_address( void )
{
unsigned int r = 0;
__asm mov dword ptr [r], esp;
return r;
}
void rec( int x, const unsigned int begin_address )
{
// here just put 100 000 bytes of memory
if ( begin_address - get_stack_address() > 100000 )
{
//std::cout << "Recursion level " << x << " stack too high" << std::endl;
return;
}
rec( x + 1, begin_address );
}
int main( void )
{
int x = 0;
rec(x,get_stack_address());
}

- 1,625
- 14
- 17
Here's a naive method, but it's a bit icky...
When you enter the function for the first time you could store the address of one of your variables declared in that function. Store that value outside your function (e.g. in a global). In subsequent calls compare the current address of that variable with the cached copy. The deeper you recurse the further apart these two values will be.
This will most likely cause compiler warnings (storing addresses of temporary variables) but it does have the benefit of giving you a fairly accurate way of knowing exactly how much stack you're using.
Can't say I really recommend this but it would work.
#include <stdio.h>
char* start = NULL;
void recurse()
{
char marker = '@';
if(start == NULL)
start = ▮
printf("depth: %d\n", abs(&marker - start));
if(abs(&marker - start) < 1000)
recurse();
else
start = NULL;
}
int main()
{
recurse();
return 0;
}
-
@MartinJames Could use a thread-local variable or simply pass the pointer as an extra argument to the worker function. But I don't see how this is better than just counting how deep the recursion is. – fuz Feb 05 '16 at 11:50
-
An alternative method is to learn the stack limit at the start of the program, and each time in your recursive function to check whether this limit has been approached (within some safety margin, say 64 kb). If so, abort; if not, continue.
The stack limit on POSIX systems can be learned by using getrlimit
system call.
Example code that is thread-safe: (note: it code assumes that stack grows backwards, as on x86
!)
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
void *stack_limit;
#define SAFETY_MARGIN (64 * 1024) // 64 kb
void recurse(int level)
{
void *stack_top = &stack_top;
if (stack_top <= stack_limit) {
printf("stack limit reached at recursion level %d\n", level);
return;
}
recurse(level + 1);
}
int get_max_stack_size(void)
{
struct rlimit rl;
int ret = getrlimit(RLIMIT_STACK, &rl);
if (ret != 0) {
return 1024 * 1024 * 8; // 8 MB is the default on many platforms
}
printf("max stack size: %d\n", (int)rl.rlim_cur);
return rl.rlim_cur;
}
int main (int argc, char *argv[])
{
int x;
stack_limit = (char *)&x - get_max_stack_size() + SAFETY_MARGIN;
recurse(0);
return 0;
}
Output:
max stack size: 8388608
stack limit reached at recursion level 174549

- 8,136
- 3
- 28
- 52
-
10 kB is not nearly enough considering how much crap you find on the stack before `main()`. Try again with a longer argument list to see that 10 kB is not sufficient. I'm wondering though, it must surely be possible to find the beginning of the stack somehow. – fuz Feb 05 '16 at 11:57
-
10 kB is a heuristic that works for me. Changed it to 64klb in the answer. One way how to learn the addresses of stack memory region is to read `/proc/
/maps` file, but that's very platform-specific. – kfx Feb 05 '16 at 12:02