This question already has answers here:
Change stack size for a C++ application in Linux during compilation with GNU compiler
(5 answers)
Closed 5 years ago.
WRT my question: Code execution breaking during recursion
I don't want to increase the stack size for every application running in my account. Just one C++ executable.
What is the way to do it?
If you really need huge amount of stack space you can make use of Boost Context and temporarily allocate a custom amount of stack space. This works on a per-thread level so it might not answer your question. However, as already said in comments, you should probably improve your algorithm as increasing stack size is hardly ever needed.
#include <boost/context/fixedsize_stack.hpp>
#include <boost/context/continuation.hpp>
void recurse(int depth)
{
std::cout << depth << std::endl;
recurse(depth + 1); // infinite recursion to test how far you can go
std::cout << depth << std::endl; // just to avoid tail recursion optimization.
}
int main(int argc, char* argv[])
{
namespace ctx = boost::context;
ctx::fixedsize_stack my_stack(100 * 1024 * 1024); // adjust stack size for your needs
ctx::continuation source =
ctx::callcc(std::allocator_arg, my_stack, [](ctx::continuation&& sink) {
// everything in here runs within a context with your custom stack.
recurse(1);
return std::move(sink);
});
// This starts the context and executes the lambda above.
source = source.resume();
return 0;
}
On Linux using GCC or Clang you could also replace fixedsize_stack with segmented_stack, which automatically grows until you run out of memory.
Boost Context is portable among most major platforms.
Related
This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 10 months ago.
When creating a pointer using new keyword or <stdlib.h>'s malloc, and put its size 0; what ever is the index number it doesnt give an error and works. ( i am not sure if this works if the size bigger then 0, because some times when i allocate a memory block and place an element outside its range program crashes).
My question : is this a c++ thing? Or just from my compiler? Is it safe to use it for arrays i don't want to limit it with specific size. Because i am thinking to use this in my game to make unlimited world generation and save it ( Not all terrain just the breakable and placable objects)
#include <iostream>
using namespace std;
int main() {
int* x = new int[0];
x[100] = 0;
cout << x[100];
return 0;
}
is this a c++ thing? Or just from my compiler?
It's a bug in your program. The behaviour of the program is undefined.
Is it safe to use it
It is not safe. The program is broken.
Prior to calling makecontext why do we need to set the stack size ss_size?
I just had an unit test case for makecontext/swapcontext snippet and it failed with SIGSEGV. What happened was that stack size was too small and unrelated memory (happened to be some unique pointers) got corrupted and reported segfault. So the segfault was on these unrelated pointers, I could have had e.g. some string and then the memory corruption would have been unnoticed.
I would have expected that SIGSEGV is beeing raised immediately when stack size ss_size does not suffice, but
considering the memory corruption described above, I conclude its impossible to recover from SIGSEGV here. That brings me back to the question, why do we need to set the stack size then in first place, when it is not being used to signal overflows? What is it used for?
EDIT:
Well it's all about makecontext(3). These functions are still being used for green threads, coroutines etc. There is just no real replacement for them considering these tasks (in my opinion) also not in c++.
ss_size defined in sigaltstack(2) is being needed for uc_stack in ucontext_t defined in getcontext(3).
Following a minimal verifiable example that shows the memory corruption, by "painting" the memory, described above.
#include <iostream>
#include <ucontext.h>
#include <memory>
#include <cstring>
#include <stdio.h>
#include <unistd.h>
ucontext_t caller, callee;
void cb(void){
//paint stack with 2
char tmp[7000];
std::memset(tmp,2,7000);
//note stack size specified 6k bytes in size
//this should not be allowed.
//furthermore there is not even some signal raised here
//i expected raised SIGSEGV when this call stack exceeds ss_size
//it makes ss_size useless no?
}
int main(){
//
std::memset(&caller,0,sizeof(caller));
std::memset(&callee,0,sizeof(callee));
//create stack and paint 0
std::unique_ptr<std::byte[]> stack(new std::byte[10000]());
std::memset(stack.get(),0,10000);//paint stack 0
//make context
//note stack specified to [2000,8000)
//that means [0,2000) and [8000,10000) should not be touched
if(getcontext(&callee) == -1) {std::cout << errno << ":" << std::strerror(errno) << std::endl; return 1;}
callee.uc_link = &caller;
callee.uc_stack.ss_sp = stack.get()+2000;
callee.uc_stack.ss_size = 6000; //what is this line good for, what is it guarding?
makecontext(&callee,cb,0);
//swap to callee
if(swapcontext(&caller,&callee) == -1) {std::cout << errno << ":" << std::strerror(errno) << std::endl; return 1;}
//print color - should be 0
//if 2 then memory corrupted by callee
std::cout << int(stack[996]) << std::endl;
std::cout << int(stack[997]) << std::endl;
std::cout << int(stack[998]) << std::endl;
std::cout << int(stack[999]) << std::endl;
return 0;
}
Once again what I don't understand is why we need to set the stack size ss_size, because it looks like that it is not being used to guard against memory corruption or anything else. It looks like it is just there to be there but without any use. But I can't believe that it has no use. So what is it "guarding" / good for?
Well, I don't want to bring more confusion into this. The goal is to get away from a fixed size function call stack by either being able to recover by installing SIGSEGV signal handler, but this looks like mission impossible due to this memory corruption; or to have a growable stack e.g. using mmap(2) with MAP_GROWSDOWN flag, but this looks broken and therefore not an option.
callee.uc_stack.ss_size = 6000; // what is this line good for, what is it guarding?
This line set's the stack size (as you could read in man sigalstack). From reading makecontext from glibc the ss_size is used for determining end of stack, where glibc setups the stack of the new context. Because stack on some machine "grows toward numerically lower addresses" (like it does on x86 architecture and wiki x86) the makecontext needs/wants to place it data on the end of the stack. So it needs to determinate the end of stack and this is what ss_size is used for.
Setting ss_size to any value does not mean that overflowing the stack size will issue a operating system signal to your process that notifies that your process tried to access restricted memory area. The implementation of *context isn't (and, well, shouldn't be) designed to make the address ss_sp + ss_size (+ 1) as kernel protected memory, so that writing to that address will trigger segmentation fault. This is still all normal variables. As always with writing to an unknown memory location and for example overflowing arrays, the invalid address may just happen to be inside your process address space, so according to the kernel the process will be writing inside it's address space and everything is fine. As you do here - your cb function writes inside new std::byte[10000] memory, from the kernel perspective there is nothing wrong with that.
You most probably could allocate new std::byte[6000] and run your process under valgrind or gdb or other tools to inspect malicious writes.
This question already has answers here:
Stack overflow caused by recursive function
(6 answers)
Closed 6 years ago.
I am trying to run this code which for some reason crashes during execution with "Segmentation fault (core dumped)" error.When i ran this in Code::Blocks debugging mode,call stack showed me a different address for pointer after after some 130000 iterations.
#include <iostream>
using namespace std;
long long counter = 0;
void test(int* ptr)
{
cout << ptr[0];
if (counter == 10000000)
return;
counter++;
test(ptr);
}
int main()
{
int arr[2];
arr[0] = 10;
arr[1] = 20;
test(&(arr[0]));
return 0;
}
(Assuming a typical stack based system) Part of the memory of a process is is designated as an execution stack. Each function call will create a frame on the stack. This frame will contain the local variables and also possibly some implementation details such as the address of the frame of the caller.
Since every function call creates a new frame on the stack, it follows that every nested function call increase the height of the stack. The stack space is not infinite. There is a platform specific limit. If you try to put too many frames on the stack, the stack will overflow. This is what happened with your program.
Solution: Do not write functions that make a huge number of recursive calls. Avoid recursive calls, when they are not necessary. For example, your recursion can be replaced by an iterative loop structure:
void test(int* ptr) {
while(counter++ != 10000000)
cout << ptr[0];
}
This question already has answers here:
Does C++ limit recursion depth?
(6 answers)
Closed 9 years ago.
#include<iostream>
using namespace std;
int f()
{
static int count=0;
count++;
if (count>=5000)
return count;
return f();
}
int main ()
{
cout<<f();
return 0;
}
this function overflows the stack after the value of count exceeds 4800 can anybody tell how to resolve this issue ?
Don't use recursion - use a regular loop. Every time you call your f() method, you will occupy few words on the stack, and you will overflow it at some point.
Usually, there's way to increase stack size (depending on your system and/or compiler), but I don't want to recommend that (especially because it will overflow again, just with the value of count bigger than 4800).
Or just int f(){ return 5000; } would do.
Assuming you want to run recursively, you could turn off debug mode, then you'll succeed (as Visual Studio adds extra stuff on the stack to detect if you "clobber" the stack [it's how it can say "The stack around variable x was overwritten" or whatever the exact message is].
However, relying on being able to do LARGE number of calls recursively is a bad plan in general - at some point or another, it will still fall over. Whether that is 5000, 50000 or 500000 is just a matter of "how much stack-space does this function take". I'd say anything that doesn't have a natural limit of around 100 levels of recursion is a case of "you are solving the problem the wrong way". If you do have such large recursion levels, it's better to use a software stack (e.g. std::stack in C++), and save the crrent state on that stack, and restore it, using the software inside the function.
Running out of stackspace is one of the worst possible runtime problems, because there is really nothing you can do - there may be things you can do to print an error message or some such, but there is really no way to "give the process some more stackspace and continue". When a process runs out of memory or something similar, you can say "Ok, I won't allocate that, and give the user an nice error message saying 'I can't do this', and the nicely save the current state and exit, for example."
[And yes, you can increase the stack-size of your application, but that really should only be done as a true last resort, and only when you fully understand WHY you need such large stack - it's very often something else you're doing wrong if you need a bigger stack].
I'm assuming this is for an academic exercise to learn about recursion. (If it is not, please don't use recursion for this!)
A better way to write your function:
#include <iostream>
int f(int i)
{
if (i >= 5000)
{
return i;
}
else
{
return f(i + 1);
}
}
int f_alt1()
{
return 5000;
}
int f_alt2()
{
int i = 0;
for (; i <= 5000; ++i);
return i;
}
int main()
{
std::cout << f(0) << std::endl;
return 0;
}
This will still eat up far more runtime resources than returning the constant or incrementing in a loop, and you will need to increase your stack size if you increase the desired constant to a significantly larger number.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is a stack overflow error?
look the code below.
#include <iostream>
using namespace std;
void leave(double as){
cout<<as;
leave(as);
}
int main(){
double x=1234.5;
leave(x);
cout<<"hellow";
}
When this code executes their is no way to stop. it should print the value x over and over again. But practically, this works for about 20 secs and close automatically. It doesn't print the line hellow. What is the reason for it? In windows task manager I can realize that the memory used with the application will increase. but I have allocated memory for x within the main function only, so will the function allocate memory for x over and over again. Is this type of situation called a memory leak? if its so what lines should be added to prevent it?
If I change the code as below it shows the word hellow without going through the function over and over again:
void leave(){
leave();
}
int main(){
leave();
cout<<"hellow";
}
How to explain these situations?
Every call to leave() results in adding a little information to the stack. When you call it recursively, the stack grows until it runs out of space, and the operating system terminates the application. In the second example, presumably the compiler optimized out the function that did nothing.