简体   繁体   中英

How to set the stacksize with C++11 std::thread

I've been trying to familiarize myself with the std::thread library in C++11, and have arrived at a stumbling block.

Initially I come from a posix threads background, and was wondering how does one setup the stack size of the std::thread prior to construction, as I can't seem to find any references to performing such a task.

Using pthreads setting the stack size is done like this:

void* foo(void* arg);
.
.
.
.
pthread_attr_t attribute;
pthread_t thread;

pthread_attr_init(&attribute);
pthread_attr_setstacksize(&attribute,1024);
pthread_create(&thread,&attribute,foo,0);
pthread_join(thread,0);

Is there something similar when using std::thread ?

I've been using the following reference:

http://en.cppreference.com/w/cpp/thread

Initially I come from a posix threads background, and was wondering how does one setup the stack size of the std::thread prior to construction, as I can't seem to find any references to performing such a task.

You can't. std::thread doesn't support this because std::thread is standardized, and C++ does not require that a machine even has a stack, much less a fixed-size one.

pthreads are more restrictive in terms of the hardware that they support, and it assumes that there is some fixed stack size per thread. (So you can configure this)

As Loki Astari already said, it is extremely rare to actually need a non-default stack-size and usually either a mistake or the result of bad coding.

  • If you feel like the default stack size is too big for your needs and want to reduce it, just forget about it. Every modern OS now uses virtual memory / on-demand commit, which means that memory is only reserved, not actually allocated, until you access the pages. Reducing the stack size will not reduce your actual memory footprint.

  • Due to this very behaviour, OSes can afford to set the default stack size to very big values. Eg on a vanilla Debian this is 8MB ( ulimit -s ) which should be enough for every need. If you still manage to hit that limit, my first idea would be that your code is wrong, so you should first and foremost review it and move things to the heap, transform recursive functions into loops, etc.

  • If despite all of this you really really need to change the stack size (ie increase it, since reducing it is useless), on POSIX you can always use setrlimit at the start of your program to increase the default stack size. Sure this will affect all threads, but only the ones who need it will actually use the additional memory.

  • Last but not least, in all fairness I can see a corner case where reducing the stack size would make sense: if you have tons of threads on a 32 bits system, they could eat up your virtual address space (again, not the actual memory consumption) up to the point that you don't have enough address space available for the heap. Again, setrlimit is your friend here even though I'd advise to move to a 64 bits system to benefit from the larger virtual address space (and if your program is that big anyway, you'll probably benefit from the additional RAM too).

I have also been investigating this issue. For some applications, the default stack size is not adequate. Examples: the program does deep recursion dependent on the specific problem it is solving; the program needs to create many threads and memory consumption is an issue.

Here is a summary of (partial) solutions / workarounds I found:

  • g++ supports a -fsplit-stack option on Linux. See for more information about Split stacks. Here is summary from their website:

The goal of split stacks is to permit a discontiguous stack which is grown automatically as needed. This means that you can run multiple threads, each starting with a small stack, and have the stack grow and shrink as required by the program.

Remark: -fsplit-stack only worked for me after I started using the gold linker . It seems clang++ will also support this flag. The version I tried (clang++ 3.3) crashed when trying to compile my application using the flag -fsplit-stack .

  • On Linux, set the stack size by executing ulimit -s <size> before starting your application. size is the stack size in Kbs. Remark: the command unlimit -s unlimited did not affect the size of threads created with std::thread . When I used ulimit -s unlimited , the main thread could grow, but the threads created with std::thread had the default size.

  • On Windows using Visual Studio, we can use use the linker /STACK parameter or /STACKSIZE in the module definition file, this is the default size for all created threads. See this link for more information. We can also modify this parameter in any executable using the command line tool EDITBIN .

  • On Windows using mingw g++, we can use the option -Wl,--stack,<size> . For some reason, when using cygwin g++, this flag only affects the size of the main thread.

Approaches that did not work for me:

  • ulimit -s <size> on OSX. It affects only the size of the main thread. Moreover, the Mac OSX default for a pthread stack size is 512kB.

  • setrlimit only affects the size of the main thread on Linux and OSX. On cygwin, it never worked for me, it seems it always returns an error.

For OSX, the only alternative seems to use boost::thread instead of std::thread , but this is not nice if we want to stick with the standard. I hope g++ and clang++ will also support -fsplit-stack on OSX in the future.

I found this in Scott Meyers book Overview of the New C++(C++0x) , as it's quite long I can't post it as a comment, is this helpful?

There is also a standard API for getting at the platform-specific handles behind threads, mutexes, condition variables, etc.. These handles are assumed to be the mechanism for setting thread priorities, setting stack sizes, etc. (Regarding setting stack sizes, Anthony Williams notes: "Of those OSs that support setting the stack size, they all do it differently. If you're coding for a specify platform (such that use of the native_handle would be OK), then you could use that platform's facilities to switch stacks. eg on POSIX you could use makecontext and swapcontext along with explicit allocation of a stack, and on Windows you could use Fibers. You could then use the platform-specific facilities (eg Linker flags) to set the default stack size to something really tiny, and then switch stacks to something bigger where necessary.“)

Was looking for the answer to this myself just now.

It appears that while std::thread does not support this, boost::thread does.

In particular, you can use boost::thread::attributes to accomplish this:

boost::thread::attributes attrs;
attrs.set_stack_size(4096*10);
boost::thread myThread(attrs, fooFunction, 42);

You can do some modifications like this if you don't want to include a big library.

It is still dependend C++ compiler STL library. (Clang / MSVC now)

HackingSTL Library

std::thread thread = std::stacking_thread(65536, []{
    printf("Hello, world!\n"); 
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM