views:

296

answers:

5

My Win32 C++ application acts as an RPC server - it has a set of functions for processing requests and RPC runtime creates a separate thread and invokes one of my functions in that thread.

In my function I have an std::auto_ptr which is used to control a heap-allocated char[] array of size known at compile time. It accidentially works when compiled with VC++ but it's undefined behaviour according to C++ standard and I'd like to get rid of it.

I have two options: std::vector or a stack-allocated array. Since I have no idea why there's a heap-allocated array I would like to consider replacing it with a stack-allocated one. The array is 10k elements and I can hypothetically face a stack overflow if the RPC runtime spawns a thread with a very small stack.

I would like to detect how much stack space is typilcally allocated to the thread and how much of it is available to my function (its callees certainly consume some of allocated space). How could I do that?

+3  A: 

In windows, the default stack size is 1MB, so you are unlikely to stack overflow with only a 10k array. That said, I think that allocating so much memory on the stack is a bad practice, and you should try to favour allocating it dynamically, if you can. There is also the Scoped Array which is well defined for automatically managing arrays - unlike the vector class, it is non-copyable.

1800 INFORMATION
I really don't see what's so bad with allocating huge arrays on stack except the risk of stack overflow.
sharptooth
The risk of stack overflow is what is bad.
Taylor Leese
+8  A: 

I don't know of any way of figuring out the stack size directly using the API if you don't have access to the CreateThread call or, if it's the main thread, looking into the EXE's default thread size in the PE header.

In your situation, I would allocate on the heap to be safe, even though a 10K array of small data is unlikely to max out the stack in non-recursive scenarios.

However, you can probe for the stack limit, if done carefully. The stack gets committed in 4K pages as you touch them (via guard pages) until you hit the limit, whereupon Windows will throw a stack overflow exception. There is still one page of stack left when the exception gets dispatched, so that the exception dispatching logic itself (including filter functions) can execute - but Windows throws the exception because it couldn't allocate another guard page. That means that the next stack overflow, or probe, will not result in a stack overflow exception, but an access violation. So to make probing work reliably (and in particular, repeatably) you need to decommit the memory allocated by the probing and reinstate a guard page.

This article on KB describes how to decommit stack memory and reinstate the guard page. It probes using recursion and 10,000-byte increments; the compiler by default implements its own stack probing for stack allocations of locals >4KB, so that the stack growth mechanism works correctly.

Barry Kelly
A: 

"std::auto_ptr which is used to control a heap-allocated char[] ... it's undefined behaviour according to C++"

It is wrong assumption! STL's auto_ptr has precise description of behavior. If you are worried about loosing control during sophisticated assignment review possibility to use reference-counter pattern to control destroying heap-allocated array.

Dewfy
auto_ptr::~auto_ptr() calls delete, not delete[] and pairing new[] with delete is undefined behaviour. That's my problem.
sharptooth
This is incorrect. You should not use auto_ptr to control an array - the behaviour of auto_ptr is defined to use `operator delete` which is undefined behaviour for heap allocated arrays.
1800 INFORMATION
@sharptooth - That is why I'm talking about own controller of allocated memory even with reference counting. The better way, of course, is leveraging std::vector, deque... But anyway stack is worst solution ever.
Dewfy
"`std::auto_ptr` which is used to control a heap-allocated `char[]`" That's about as much undefined behavior as you can get.
sbi
@sbi point of preceding of heap allocated array over stack allocated. allocate thousands of bytes in stack is the worst solution.
Dewfy
+1  A: 

I second 1800 INFORMATION:

  • Allocate your data on heap if you can. It's safer (e.g. buffer overflows are harder to exploit) and more flexible when (not if) you need to extend your design later.

  • Use std::vector, boost::scoped_array or boost::shared_array.

I know it's not answering your question on detecting stack size but I think it's a logical answer to your problem.

Tomek Szpakowicz
+1  A: 

I'm not sure what you're after.

If you just want typical numbers, then go ahead and try! Create a function with nested scopes, each of which allocates some more stack space. Output in each scope. See how far the thing gets.

If you want concrete numbers in a concrete situation, ask yourself what you would want to do once you have them? Branch into different implementations? This sounds like a maintenance problem the use of which should be very well justified. What do you expect to gain? Is this really worth such a hassle?

I agree that 10k usually shouldn't be a problem. So if your code isn't mission critical, go ahead and use boost::array (or std::tr1::array, if your std lib comes with it). Otherwise just use std::vector or, if you feel you must, boost::scoped_array (or std::tr1::scoped_array, if your std lib comes with it).

sbi