I was just going through this Wikipedia entry. Out of curiosity to find the stack size allocated to a simple process, i tried this
int main()
{
static int count = 0;
cout<<" Count = "<<count++<<endl;
main();
return 0;
}
Compiler DevC++
I got this :-
Till this point everything is fine, understandable, by the way from last digit i.e. 43385 can i guess the maximum stack size - on 32 bit machine (what if i say 4 bytes(4 bytes for return address on stack for each call), i may sound silly on this.
Now if i modify my program to :-
void foo()
{
static int count = 0;
cout<<" Count = "<<count++<<endl;
foo();
}
int main()
{
foo();
return 0;
}
In this i get Stack Over flow at count :- 130156 (ok, fine)
But my question if, i add one function in between main and foo, i get this count decrements by 1(130155), if 2 functions in b/w foo and main count is decremented by 2(130154) and so on. Why is this behavior? Is it because 1 space is being consumed for each function address.
Firstly correct your program by adding Count++ (silly).
Stack size is not fixed, most compilers let you specify the Stack size. Stack size is also dependent on some factors like Platform, toolchain, ulimit,and other parameters.There are many static and dynamic properties that can influence it.
There are three kinds of memory limits:
for 32-bit (windows)
Static data - 2GB
Dynamic data - 2GB
Stack data - 1GB (the stack size is set by the linker, the default is 1MB. This can be increased using the Linker property System > Stack Reserve Size).
by using your program you can guess the current stack size.
The memory-limits-applications-windows Stack Overflow Recursion in C c-maximum-stack-size-of-program will help you.
Related
We all know that stack is growing downward, so it's really a straightforward assumption that if we find the address of the last declared variable, we will get out the smallest address in stack, so we could just assume that this address will be our residual available stack.
And i did it, and i got just humongous address {0x000000dc9354f540} = {947364623680} we know that stack growing downward and we know that we can't go lower than 0.
so a bit of math:
947364623680 / (1024*1024*1024) = 882.302060425
--> Do they imply that i have 882Gb of stack on my machine?!
I test it and obviously get the stack overflow exception after allocating additional 2mb on stack:
uint8 array[1024*1024*2] = {};
And there my question come WTF is this, and how can i get my actual stack size?
Since you question has a tag "visual-studio-debugging" I assume you use windows.
First you should get the current stack pointer. Either get an address of a local dummy variable (like you did now), or by raw asm read esp/rsp, or get an address of a local dummy variable (like you did now), or get CPU register via Win32 API call to GetThreadContext).
Now, in order to find out the available stack size you may use VirtualQuery to see the starting address of this virtual memory region (aka allocation base address). Basically subtracting those pointers would give you the remaining stack size (precision up to the size of the current stack frame).
Long time ago I've written an article about this subject, including querying the currently allocated/reserved stack size. You can find out more info there if you want:
Do they imply that i have 882Gb of stack on my machine?!
It has nothing to do with the "stack on your machine". It's about virtual address space, which has nothing to do with the physical storage (RAM + page files) available in the system.
Another approach to get an approximate value of the stack space left at any given point in a win32 application would be something like the following function. It uses structured exception handling to catch the stack overflow exception.
Note: #valdo's solution is the correct solution. I'm posting this answer because it's kind of an interesting way to solve it. It's going to be very slow because it's runtime is linear (in terms of stack size), as opposed to constant runtime of #valdo's solution.
static uint64_t GetAvailableStackSpace()
{
volatile uint8_t var;
volatile uint8_t* addr = &var;
volatile uint8_t sink;
auto filter = [](unsigned int code) -> int
{
return (code == EXCEPTION_STACK_OVERFLOW) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
};
__try
{
while (true)
{
addr = addr - 1024;
sink = *addr;
}
}
__except (filter(GetExceptionCode()))
{
return (&var - addr);
}
return 0;
}
This is an implementation of the VirtualQuery technique mentioned by #valdo.
This function returns an approximate number of bytes of stack available. I tested this on Windows x64.
static uint64_t GetAvailableStackSpace()
{
volatile uint8_t var;
MEMORY_BASIC_INFORMATION mbi;
auto virtualQuerySuccess = VirtualQuery((LPCVOID)&var, &mbi, sizeof(mbi));
if (!virtualQuerySuccess)
{
return 0;
}
return &var - mbi.AllocationBase;
}
I'm a beginner in C++. Yesterday I read about recursive functions, so I decided to write my own. Here's what I wrote:
int returnZero(int anyNumber) {
if(anyNumber == 0)
return 0;
else {
anyNumber--;
return returnZero(anyNumber);
}
}
When I do this: int zero1 = returnZero(4793);, it causes a stack overflow. However, if I pass the value 4792 as the argument, no overflow occurs.
Any ideas as to why?
Whenever you call a function, including recursively, the return address and often the arguments are pushed onto the call stack. The stack is finite, so if the recursion is too deep you'll eventually run out of stack space.
What surprises me is that it only takes 4793 calls on your machine to overflow the stack. This is a pretty small stack. By way of comparison, running the same code on my computer requires ~100x as many calls before the program crashes.
The size of the stack is configurable. On Unix, the command is ulimit -s.
Given that the function is tail-recursive, some compilers might be able to optimize the recursive call away by turning it into a jump. Some compilers might take your example even further: when asked for maximum optimizations, gcc 4.7.2 transforms the entire function into:
int returnZero(int anyNumber) {
return 0;
}
This requires exactly two assembly instructions:
_returnZero:
xorl %eax, %eax
ret
Pretty neat.
You just hit the call stack's size limit of your system, that's what's happening. For some reason the stack in your system is tiny, a depth of 4793 function calls is rather small.
Your stack is limited in size and so when you make 4793 calls you are hitting the limit while 4792 just comes in under. Each function call will use some space on the stack for house keeping and maybe arguments.
This page gives an example of what a stack looks like during a recursive function call.
My guess is you stack is exactly big enough to fit 4792 entries - today. Tomorrow or the next, that number might be different. Recursive programming can be dangerous and this example illistrates why. We try not to let recursion get this deep or 'bad' things can happen.
Any "boundless" recursion, that is recursive calls that aren't naturally limited to a small(ish) number will have this effect. Exactly where the limit goes depends on the OS, the environment the function is called in (the compiler, which function calls the recursive function, etc, etc).
If you add another variable, say int x[10]; to your function that calls your recursive function, the number needed to crash it will change (probably by about 5 or so).
Compile it with a different compiler (or even different compiler settings, e.g. optimization turned on) and it will probably change again.
Using recursion, you can achieve SuperDigit:
public class SuperDigit
{
static int sum = 0;
int main()
{
int n = 8596854;
cout<<getSum(n);
}
int getSum(int n){
sum=0;
while (n > 0) {
int rem;
rem = n % 10;
sum = sum + rem;
n = n / 10;
getSum(n);
}
return sum;
}
}
I’d like to understand the call-stack a bit better, and in an effort to do so, I’d like to work with it some more.
What will I do with this information? I have no idea! It’s fun to learn new things though, and this is my new thing for today.
I don’t like the call-stack in my programs being this mystical entity that I know nothing about. How big is it? How much memory is available on my current call-stack? Where is it? I don't know! And, I would like to know.
My current way to deal with the call-stack is to be aware of it, but to not knowingly interact with it until I hit a stack overflow error. That's just not good enough!
So in my quest, I’d like to figure out how to do the following:
I'd like to know the total size of the current call-stack that I'm operating on.
I'd like to calculate the total available memory available on my current call-stack.
I’d like to be able to find the address of where my call-stack starts.
The declaration could look like this, and be filled in for various platforms:
class call_stack
{
inline static void* base_address();
inline static void* end_address();
inline static std::size_t size();
inline static std::size_t remaining();
};
How is stack information defined on current desktop and mobile platforms, and how can I access it? How can I code this at compile time, or determine it at runtime?
Looking into this reminds me of a talk that Herb Sutter gave about atomics. He said something along the lines of “as C++ programmers, we like to push the big red buttons that say don’t touch.”
I realize there are many questions about the call-stack, and I believe that mine is both meaningful and unique.
Other questions on the call-stack topic don't ask about the call-stack in a similarly broad manner to what I'm asking here.
The Stack
In modern platforms, the stack structure is simplified to using a pointer to where the next item should be inserted. And most platforms use a register to do this.
+---+
| |
+---+
| |
+---+
| |
+---+
| | <-- Next available stack slot
+---+
An item is written at the present location of the stack pointer, then the stack pointer is incremented.
The CALL Stack
The minimum that needs to be pushed onto the stack is the return address or address of next instruction after the call. This is about as common as you get. Anything else that is pushed onto the stack depends on the protocol set up by the compiler or operating system.
For example, the compiler my choose to place parameters into registers rather than pushing them onto the stack.
The order of the parameters depends ultimately on the compiler (and language). The compiler may push the leftmost value first or the last parameter first.
Stack Starting Address
The Stack Starting Address is usually determined by the operating systems, or on embedded systems, at a fixed location. There is no guarantee that the operating system will place your program's stack in the same location for every invocation.
Stack Size
There are two terms here: capacity and content. Stack size can refer to the number of elements in the stack (content) or the capacity that the stack can hold.
There is no fixed, common limit here. Platforms differ. Usually the OS is involved in allocating the capacity of the stack. And on many platforms, the OS doesn't check to see if you have exceeded the capacity.
Some Operating Systems provide mechanisms so that the executable can adjust the capacity of the stack. Most OS providers usually provide an average amount.
Sharing Memory with Heap
A common setup is to have the stack grow towards the heap. So all the extra memory for a process is allocated so that, for example, the stack grows from the beginning of the extra memory down and the heap allocates from the bottom up. This allows for programs that use little dynamic memory to have more stack space and those that use little stack space to have more dynamic memory. The big issue is when they cross. No notification, just undefined behavior.
Accessing Stack Information
Most of the time, I never look at the values of the stack pointer or register. This is usually on performance critical systems that have restricted memory capacities (like embedded systems).
The stack is usually reviewed by the debugger to provide a call trace.
None of what you ask can be done in standard c++ since the stack is not specified in the standard.
You may be able to access that information by reading cpu registers in assembly language. How to do that depends on the cpu architecture, the OS and possibly the calling convention used by the compiler. Best place to find the information you're looking for is the manual for the architecture, OS, etc. The platfrom may also provide the information through system calls or virtual filesystems.
As an example, here's a quick look at the wikipedia page for the common x86 architecture
SP/ESP/RSP: Stack pointer for top address of the stack.
BP/EBP/RBP: Stack base pointer for holding the address of the current stack frame.
You can unwind the stack and find find the top of the stack in the first call frame. How to unwind the stack is again, specific to calling convention used. Subtracting the base of the first stack frame with the current stack pointer would give you the current size of the stack. Also remember that each thread has their own call stack so you must subtract from the bottom of the stack of the correct thread.
But keep in mind that:
Although the main registers (with the exception of the instruction pointer) are "general-purpose" in the 32-bit and 64-bit versions of the instruction set and can be used for anything...
You should check the manual of your target platform before assuming what the registers are used for.
Getting the remaining / total maximum stack space can be a bit trickier. In Linux the stack size is typically limited during runtime. The limit can be accessed through the /proc/ filesystem or using system calls. In Windows, the maximum stack size can be set at linktime and should be accessible in the executable file headers.
Below is an example program that works on Linux. I read the start of stack from /proc/<pid>/stat. I also provide an example for unwinding and for that I use a library that abstracts away all the OS / architecture specific assembly code. The stack is unwound all the way up to the initialization code before main and the stack space used by that is accounted for.
I use SP register instead of BP to get the bottom of the stack in the fisrt call frame because BP does not exist in some architectures and on my platform it was zero in the initialization frames. That means that the bottom is off by the size of the first call frame and is therefore just an approximation. See it on coliru, unfortunately access to /proc/<pid>/stat is denied there.
#include <iostream>
using namespace std;
#include <fstream>
#include <sstream>
#include <unistd.h>
// read bottom of stack from /proc/<pid>/stat
unsigned long bottom_of_stack() {
unsigned long bottom = 0;
ostringstream path;
path << "/proc/" << getpid() << "/stat";
ifstream stat(path.str());
// possibly not the best way to parse /proc/pid/stat
string ignore;
if(stat.is_open()) {
// startstack is the 28th field
for(int i = 1; i < 28; i++)
getline(stat, ignore, ' ');
stat >> bottom;
}
return bottom;
}
#include <sys/resource.h>
rlim_t get_max_stack_size() {
rlimit limits;
getrlimit(RLIMIT_STACK, &limits);
return limits.rlim_cur;
}
#define UNW_LOCAL_ONLY
#include <libunwind.h>
// using global variables for conciseness
unw_cursor_t frame_cursor;
unw_context_t unwind_context;
// approximate bottom of stack using SP register and unwinding
unw_word_t appr_bottom_of_stack() {
unw_word_t bottom;
unw_getcontext(&unwind_context);
unw_init_local(&frame_cursor, &unwind_context);
do {
unw_get_reg(&frame_cursor, UNW_REG_SP, &bottom);
} while(unw_step(&frame_cursor) > 0);
return bottom;
}
// must not inline since that would change behaviour
unw_word_t __attribute__((noinline)) current_sp() {
unw_word_t sp;
unw_getcontext(&unwind_context);
unw_init_local(&frame_cursor, &unwind_context);
unw_step(&frame_cursor); // step to frame before this function
unw_get_reg(&frame_cursor, UNW_REG_SP, &sp);
return sp;
}
// a little helper for absolute delta of unsigned integers
#include <algorithm>
template<class UI>
UI abs_udelta(UI left, UI right) {
return max(left,right) - min(left,right);
}
unsigned long global_bottom;
rlim_t global_max;
// a test function to grow the call stack
int recurse(int index) {
if(index < 2 ) {
auto stack_size = abs_udelta(current_sp(), global_bottom);
cout << "Current stack size: " << stack_size
<< "\tStack left: " << global_max - stack_size << '\n';
return index;
}
return recurse(index - 1) + recurse(index - 2); // do the fibonacci
}
int main() {
global_max = get_max_stack_size();
global_bottom = bottom_of_stack();
auto appr_bottom = appr_bottom_of_stack();
cout << "Maximum stack size: "
<< global_max << '\n';
cout << "Approximate bottom of the stack by unwinding: "
<< (void*)appr_bottom << '\n';
if(global_bottom > 0) {
cout << "Bottom of the stack in /proc/<pid>/stat: "
<< (void*)global_bottom << '\n';
cout << "Approximation error: "
<< abs_udelta(global_bottom, appr_bottom) << '\n';
} else {
global_bottom = appr_bottom;
cout << "Could not parse /proc/<pid>/stat" << '\n';
}
// use the result so call won't get optimized out
cout << "Result of recursion: " << recurse(6);
}
Output:
Maximum stack size: 8388608
Approximate bottom of the stack by unwinding: 0x7fff64570af8
Bottom of the stack in /proc/<pid>/stat: 0x7fff64570b00
Approximation error: 8
Current stack size: 640 Stack left: 8387968
Current stack size: 640 Stack left: 8387968
Current stack size: 576 Stack left: 8388032
Current stack size: 576 Stack left: 8388032
Current stack size: 576 Stack left: 8388032
Current stack size: 576 Stack left: 8388032
Current stack size: 576 Stack left: 8388032
Current stack size: 512 Stack left: 8388096
Current stack size: 576 Stack left: 8388032
Current stack size: 576 Stack left: 8388032
Current stack size: 512 Stack left: 8388096
Current stack size: 512 Stack left: 8388096
Current stack size: 512 Stack left: 8388096
Result of recursion: 8
linux: start here http://man7.org/linux/man-pages/man3/backtrace.3.html
windows: start here: http://msdn.microsoft.com/en-us/library/windows/desktop/bb204633(v=vs.85).aspx
Here's a way to get a rough estimate of the size of the current call stack.
In main(), save the address of argc to a global variable. This is somewhat close to where your stack starts. Then when you want to check the current size, take the address of the first argument to your current function and subtract it from your saved value. This will be less accurate if you have a large amount of data in automatic variables in main() or the current function (I'm not sure which one - it may vary by platform).
There are probably cases where the stack grows dynamically by chaining blocks, in which case this technique will not be accurate.
In a multithreaded program, you would have to track the start of each thread's stack separately. Similarly to main, get the address of one of the parameters to the top-level thread function when the thread starts up.
I wish I had thought to save the link to the page where I found someone doing something similar. They got the address of one of the automatic variables instead of one of the parameters, which would still give a very similar result.
I would like to use a large array on the stack. However I keep on getting stack overflow although I changed the stack reserve size.
For example:
int main()
{
int a[5000000];
return 0;
}
and in visual studio 2012: Properties -> Linker -> System -> Stack reserve size: 10000000
What could cause it?
The size of an int is probably 4 bytes, so the array is larger in bytes than in the number of elements. sizeof(int)*5000000 is what you need. (at least)
I'm a beginner in C++. Yesterday I read about recursive functions, so I decided to write my own. Here's what I wrote:
int returnZero(int anyNumber) {
if(anyNumber == 0)
return 0;
else {
anyNumber--;
return returnZero(anyNumber);
}
}
When I do this: int zero1 = returnZero(4793);, it causes a stack overflow. However, if I pass the value 4792 as the argument, no overflow occurs.
Any ideas as to why?
Whenever you call a function, including recursively, the return address and often the arguments are pushed onto the call stack. The stack is finite, so if the recursion is too deep you'll eventually run out of stack space.
What surprises me is that it only takes 4793 calls on your machine to overflow the stack. This is a pretty small stack. By way of comparison, running the same code on my computer requires ~100x as many calls before the program crashes.
The size of the stack is configurable. On Unix, the command is ulimit -s.
Given that the function is tail-recursive, some compilers might be able to optimize the recursive call away by turning it into a jump. Some compilers might take your example even further: when asked for maximum optimizations, gcc 4.7.2 transforms the entire function into:
int returnZero(int anyNumber) {
return 0;
}
This requires exactly two assembly instructions:
_returnZero:
xorl %eax, %eax
ret
Pretty neat.
You just hit the call stack's size limit of your system, that's what's happening. For some reason the stack in your system is tiny, a depth of 4793 function calls is rather small.
Your stack is limited in size and so when you make 4793 calls you are hitting the limit while 4792 just comes in under. Each function call will use some space on the stack for house keeping and maybe arguments.
This page gives an example of what a stack looks like during a recursive function call.
My guess is you stack is exactly big enough to fit 4792 entries - today. Tomorrow or the next, that number might be different. Recursive programming can be dangerous and this example illistrates why. We try not to let recursion get this deep or 'bad' things can happen.
Any "boundless" recursion, that is recursive calls that aren't naturally limited to a small(ish) number will have this effect. Exactly where the limit goes depends on the OS, the environment the function is called in (the compiler, which function calls the recursive function, etc, etc).
If you add another variable, say int x[10]; to your function that calls your recursive function, the number needed to crash it will change (probably by about 5 or so).
Compile it with a different compiler (or even different compiler settings, e.g. optimization turned on) and it will probably change again.
Using recursion, you can achieve SuperDigit:
public class SuperDigit
{
static int sum = 0;
int main()
{
int n = 8596854;
cout<<getSum(n);
}
int getSum(int n){
sum=0;
while (n > 0) {
int rem;
rem = n % 10;
sum = sum + rem;
n = n / 10;
getSum(n);
}
return sum;
}
}