I call the method and get StackOverflowException. It is not recursive call and it just contains array initialization. I need an array of BigIntegers, the code works fine with int array even of much bigger size. I show simplified example and in real code I can't use loop to fill the array as I can't generate numbers I need, so I have to hard code them all.
Setup: x64 mode, .Net Core
From error details we can see that:
1) Stack trace is null
2) Error presumably originated in System.Collections.ListDictionaryInternal
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Before"); // <--- This is displayed
var a = GetBigIntegers(); // <--- Method is called
Console.WriteLine("After"); // <--- We will never get there
}
static BigInteger[] GetBigIntegers()
{
// <--- Crash here
return new BigInteger[]
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
// Many more lines (850-900) and they are 2-3 times longer than here
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
};
}
}
I've checked IL code, it looks correct and it takes close to 400 000 lines.
.method private hidebysig static
valuetype [System.Runtime.Numerics]System.Numerics.BigInteger[] GetBigIntegers () cil managed
{
// Method begins at RVA 0x207c
// Code size 1130123 (0x113e8b)
.maxstack 4
.locals init (
[0] valuetype [System.Runtime.Numerics]System.Numerics.BigInteger[]
)
// (no C# code)
IL_0000: nop
IL_0001: ldc.i4 66500
IL_0006: newarr [System.Runtime.Numerics]System.Numerics.BigInteger
IL_000b: dup
IL_000c: ldc.i4.0
// return new BigInteger[66500]IL_000d: ldc.i4.1
IL_000e: call valuetype [System.Runtime.Numerics]System.Numerics.BigInteger [System.Runtime.Numerics]System.Numerics.BigInteger::op_Implicit(int32)
// (no C# code)
IL_0013: stelem [System.Runtime.Numerics]System.Numerics.BigInteger
IL_0018: dup
IL_0019: ldc.i4.1
IL_001a: ldc.i4.1
IL_001b: call valuetype [System.Runtime.Numerics]System.Numerics.BigInteger [System.Runtime.Numerics]System.Numerics.BigInteger::op_Implicit(int32)
IL_0020: stelem [System.Runtime.Numerics]System.Numerics.BigInteger
.....
IL_113e75: dup
IL_113e76: ldc.i4 66499
IL_113e7b: ldc.i4.1
IL_113e7c: call valuetype [System.Runtime.Numerics]System.Numerics.BigInteger [System.Runtime.Numerics]System.Numerics.BigInteger::op_Implicit(int32)
IL_113e81: stelem [System.Runtime.Numerics]System.Numerics.BigInteger
IL_113e86: stloc.0
IL_113e87: br.s IL_113e89
IL_113e89: ldloc.0
IL_113e8a: ret
} // end of method Program::GetBigIntegers
I expected that array will be initialized and returned, but actually I got StackOverflow error.
I know that I can use different approaches to do the same stuff, but I want to know WHY it doesn't work this way. Hope it is interesting to everyone reading this question too.
The actual reason is that evaluation stack frame size is not big enough to fit in everything pushed into.
The reason for that is hiding behind JIT-compiler optimizations which are not performed for struct initialization inside big methods (which leads to poor-perfomance machine code being generated).