Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I have a simple example of some code that causes a stack overflow exception and wondered if this was a common issue or some kind of bug.

I am using a console app to generate some data. It adds around 20000 objects to a collection. Some of the fields are nullable. If I make them bool? then it works but if I change a couple of them (as I have in the sample code) to decimal? then it throws the exception.

It also only does this when I physically add 20000 Add(... lines. If I do it in a loop then it work fine (this is in the example as well).

Apologies for the length of the code example. Any help would be appreciated.

using System.Collections.Generic;
    using System;

    namespace StackOverflow
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine($"{new UpdateCommands().Count} commands");
                Console.WriteLine($"{new CreateCommands().Count} commands");
                Console.ReadKey();
            }
        }
    }

    public class CreateCommand
    {
        public CreateCommand(string code, string name, string label, string field1, string field2, string field3,
            bool? field4, bool? field5, bool? field6, bool? field7, decimal? field8, decimal? field9, decimal? field10, decimal? field11)
        {
        }
    }

    public class UpdateCommands : List<CreateCommand>
    {
        public UpdateCommands()
        {
            for (int i = 0; i < 22000; i++)
            {
                Add(new CreateCommand("code", "name", "label", "", null, null, null, null, null, null, null, null, null, null));
            }
        }
    }

    public class CreateCommands : List<CreateCommand>
    {
        public CreateCommands()
        {

            Add(new CreateCommand("code", "name", "label", "", null, null, null, null, null, null, null, null, null, null));

you need to copy the line above 22000 times
        }
    }
share|improve this question
1  
That will not compile because there is no CreateCommands class. And if you meant new CreateCommand that doesn't have a parameterless constructor nor does it define a Count method. – juharr Dec 5 at 16:13
    
I think the purpose of question is about why you get stackoverflow when there is lots of lines. This is not stupid question. because OP already knows how to use loop and this is for learning purpose. – M.kazem Akhgary Dec 5 at 16:14
    
I just tested this and the first line in the Main method runs fine. The second does not compile, so you need to give use more info in order to figure out what is going on. – juharr Dec 5 at 16:16
    
@juharr It does have a parameterless constructor. It has Count in that it is inherited from the base class. – Servy Dec 5 at 16:16
    
@Servy I was talking about the second line with new CreateCommands(). – juharr Dec 5 at 16:17

Essentially, the size of the stack is limited, so you may run into a StackOverflowException also in absence of an infinite loop.

The following IL code is generated for each Add-call in Debug mode:

.maxstack 15
.locals init (
    [0] valuetype [mscorlib]System.Nullable`1<bool>,
    [1] valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>
)
IL_0357: nop
IL_0358: ldarg.0
IL_0359: ldstr "code"
IL_035e: ldstr "name"
IL_0363: ldstr "label"
IL_0368: ldstr ""
IL_036d: ldnull
IL_036e: ldnull
IL_036f: ldloca.s 0
IL_0371: initobj valuetype [mscorlib]System.Nullable`1<bool>
IL_0377: ldloc.0
IL_0378: ldloca.s 0
IL_037a: initobj valuetype [mscorlib]System.Nullable`1<bool>
IL_0380: ldloc.0
IL_0381: ldloca.s 0
IL_0383: initobj valuetype [mscorlib]System.Nullable`1<bool>
IL_0389: ldloc.0
IL_038a: ldloca.s 0
IL_038c: initobj valuetype [mscorlib]System.Nullable`1<bool>
IL_0392: ldloc.0
IL_0393: ldloca.s 1
IL_0395: initobj valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>
IL_039b: ldloc.1
IL_039c: ldloca.s 1
IL_039e: initobj valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>
IL_03a4: ldloc.1
IL_03a5: ldloca.s 1
IL_03a7: initobj valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>
IL_03ad: ldloc.1
IL_03ae: ldloca.s 1
IL_03b0: initobj valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>
IL_03b6: ldloc.1
IL_03b7: newobj instance void CreateCommand::.ctor(string, string, string, string, string, string, valuetype [mscorlib]System.Nullable`1<bool>, valuetype [mscorlib]System.Nullable`1<bool>, valuetype [mscorlib]System.Nullable`1<bool>, valuetype [mscorlib]System.Nullable`1<bool>, valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>, valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>, valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>, valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.Decimal>)
IL_03bc: call instance void class [mscorlib]System.Collections.Generic.List`1<class CreateCommand>::Add(!0)

(line numbers are of course different per iteration and the first two declarations are not repeated)

In this piece of code, the stack should remain in equal size, with maxstack calculated to be 15. Thus, a StackOverflow exception here is a bug because the JIT does not correctly get rid of stack entries. What JITters have you tried?

share|improve this answer
    
Just the standard. Also tried in V4, 4.5 and 4.6 of the framework. – Dave Dec 6 at 7:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.