Recently I've tested the limit of a stack on three devices with different OSs (by limit, I mean the maximum number of levels that can the stack have), and I noticed that every time when I hit 2^16 levels it gives me overflow error, and when I put 2^16-1 it works properly.
So my question is – is that true? Does the stack has the maximum limit 2^16-1 by definition or it depends on the OS?
Best Answer
It is strongly operating system specific (& computer specific) and on some OSes you have some ways to configure (and even increase) the limit. It is even compiler specific (or your-programming-language-implementation specific), since some compilers (including recent GCC for some limited kind of C code) are able to optimize some tail calls.
(some programming language specifications require tail call optimizations, e.g. R5RS)
I'm not sure your question makes sense (and certainly not your 216 limit). On my Linux desktop (Debian/Sid/x86-64, Linux 4.9 kernel, 32Gb RAM, Intel i5-4690S), I might have a call stack of up to 8 megabytes (and I could increase that limit, if I really wanted to).
Multi-threading and ASLR are making your question much more complex. See e.g. pthread_attr_setstack(3). Read also about split stacks (often used by Go implementations) and about continuation passing style. See also this answer.
For what it is worth, I just tried the following C99 (and also C11) code:
and I was able to run that
recur
program (compiled with GCC 6 asgcc -Wall -O recur.c -o recur
) asrecur 161000
(so much above your 216 limit). Withrecur 256000
it also worked. Withrecur 456000
it crashed (with a stack overflow for levelx=272057
). I don't have the patience for other tests. Try that on your computer. Don't forget to ask for optimizations.A rule of thumb (for desktops, laptops, tablets) might be to keep your call stack below one megabyte.
By passing also
-fstack-usage
togcc
I'm getting the followingrecur.su
file (numbers are in bytes, consistent with my 8Mb stack limit intuition; don't forget themain
call frame, and more importantly the initial stack layout, installed by the kernel when doing execve(2)..., for crt0):PS. My Arduino has a Atmega328 with only 2Kbytes of RAM, so certainly cannot recur that much. I guess only a few hundreds stack frames are at most practically possible on Arduinos.