Is there a standard way to see how much stack space your app has and what the highest watermark for stack usage is during a run?
Also in the dreaded case of actual overflow what happens?
Does it crash, trigger an exception or signal? Is there a standard or is it different on all systems and compilers?
I'm looking specifically for Windows, Linux and Macintosh.
A method of detecting stack overflows is to create a canary space at the end of each task. This space is filled with some known data. If this data is ever modified, then the application has written past the end of the stack.
One way to retrieve the exact location of the stack is to look at the file /proc/1234/maps (where 1234 is the process ID of your program). Once you know these bounds you can compute how much of your stack is used by looking at the address of the latest local variable.
The most-common cause of stack overflow is excessively deep or infinite recursion, in which a function calls itself so many times that the space needed to store the variables and information associated with each call is more than can fit on the stack. An example of infinite recursion in C.
A stack overflow is a type of buffer overflow error that occurs when a computer program tries to use more memory space in the call stack than has been allocated to that stack.
On Windows a stack overflow exception will be generated.
The following windows code illustrates this:
#include <stdio.h> #include <windows.h> void StackOverFlow() { CONTEXT context; // we are interested control registers context.ContextFlags = CONTEXT_CONTROL; // get the details GetThreadContext(GetCurrentThread(), &context); // print the stack pointer printf("Esp: %X\n", context.Esp); // this will eventually overflow the stack StackOverFlow(); } DWORD ExceptionFilter(EXCEPTION_POINTERS *pointers, DWORD dwException) { return EXCEPTION_EXECUTE_HANDLER; } void main() { CONTEXT context; // we are interested control registers context.ContextFlags = CONTEXT_CONTROL; // get the details GetThreadContext(GetCurrentThread(), &context); // print the stack pointer printf("Esp: %X\n", context.Esp); __try { // cause a stack overflow StackOverFlow(); } __except(ExceptionFilter(GetExceptionInformation(), GetExceptionCode())) { printf("\n****** ExceptionFilter fired ******\n"); } }
When this exe is run the following output is generated:
Esp: 12FC4C Esp: 12F96C Esp: 12F68C ..... Esp: 33D8C Esp: 33AAC Esp: 337CC ****** ExceptionFilter fired ******
On Linux you get a segmentation fault if your code tries to write past the stack.
The size of the stack is a property inherited between processes. If you can read or modify it in the the shell using commands like ulimit -s
(in sh
, ksh
, zsh
) or limit stacksize
(tcsh
, zsh
).
From a program, the size of the stack can be read using
#include <sys/resource.h> #include <stdio.h> int main() { struct rlimit l; getrlimit(RLIMIT_STACK, &l); printf("stack_size = %ld\n", l.rlim_cur); return 0; }
I don't know of a standard way to get the size of the available stack.
The stack starts with argc
followed by the contents of argv
and a copy of the environment, and then your variables. However because the kernel can randomize the location of the start of the stack, and there can be some dummy values above argc
, it would be wrong to assume that you have l.rlim_cur
bytes available below &argc
.
One way to retrieve the exact location of the stack is to look at the file /proc/1234/maps
(where 1234
is the process ID of your program). Once you know these bounds you can compute how much of your stack is used by looking at the address of the latest local variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With