4

I am operating with a large array of struct types in .NET that is far larger than the standard 1MB allocated for the stack (per thread). I am only concerned with the main thread for now.

  1. I have read an old article (possibly outdated) that mentions explicitly sizing your stack: http://content.atalasoft.com/h/i/58213648-increasing-the-size-of-your-stack-net-memory-management-part-3

  2. I have noticed that my programs frequently crash with stackoverflow exceptions when in 32-bit mode BUT not in 64 bit mode (my primary mode of interest).

Tentative Hypothesis

  1. You need to explicitly increase the size of the stack when you're in 32-bit mode.

  2. The .NET framework implicitly resizes the stack for you in 64-bit mode (even though this behaviour is not consistent with 64-bit mode).

whitebox
  • 75
  • 5

1 Answers1

4

The C# and VB.NET compilers don't have a way to specify the main thread's initial stack size. The C++/CLI compiler does. Using Editbin.exe in a post-build event is otherwise a simple workaround.

This option was not exposed because the default stack size is very generous for managed code. Unlike unmanaged languages like C and C++, there is no simple way to consume large amounts of stack with declarations. Arrays and strings are reference types so are allocated on the GC heap, not the stack.

The only decent way to blow the stack is by using the unsafe stackalloc keyword, one you never use by accident. Or by recursion, either accidental (by far the most common case) or using a recursive algorithm that's worse than O(logN). Such problems heavily lean toward bug, Editbin.exe is just a band-aid because you will still blow the stack when the dataset is large enough.

Only other detail worth noting is that the initial stack size will be 4MB instead 1MB if you specifically target x64. Generally a mistake as well, you always favor AnyCPU.


So the otherwise blind advice is to start looking for that recursion code. It should not be located very far from the statement that generated the SOE, at least visible in the stack trace. Watch out for O(N) tail-cursive, you can't count on it getting optimized, definitely not in 32-bit code. Consider replacing it or partitioning it or adding a check to the dataset size and throw an exception pre-emptively.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I think it's worth elaborating on the tail call optimization, which is a significant difference between x86 and x64 JIT behaviors, which much larger effect on propensity to throw StackOverflowException than the thread stack size. – Ben Voigt Nov 15 '15 at 16:03