Skip to content

System.ValueTuple causes a StackOverflow when used in a large Dictionary. #8980

@jcouv

Description

@jcouv

Moved (and edited) this issue from the roslyn repo.

Summary: you add an empty Main method to the attached code, then compile it with csc.exe geocoords_stackoverflow.cs.txt. When you run the resulting executable, you get an overflow error (Process is terminated due to StackOverflowException.)

From discussion with @VSadov, we think this is a JIT issue rather than a compiler issue.
FYI @jkotas for triage. Thanks


@andras-ferencz commented on Tue Feb 28 2017

When using the new System.ValueTuple in a large Dictionary, I receive a stack overflow exception where as I do not with System.Tuple.

Dictionary<int, (double lat, double lon)> zipcodes = new Dictionary<int, (double lat, double lon)>() {{123,(18.180555,-66.749961)} }; works fine just for reference.

geocoords_stackoverflow.cs.txt
geocoords_worksfine.cs.txt


@jcouv commented on Tue Feb 28 2017

I'm able to see the repro file. The code causing stack overflow looks like this:

using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Net.Mail;

namespace HAL
{
    public static partial class geo
    {
        public static Dictionary<int,(double lat, double lon)> zipcodes = new Dictionary<int, (double lat, double lon)>()
{{00601,(18.180555,-66.749961)},
{00602,(18.361945,-67.175597)},
{00603,(18.455183,-67.119887)},
{00606,(18.158345,-66.932911)},
{00610,(18.295366,-67.125135)},
{00612,(18.402253,-66.711397)},
{00616,(18.420412,-66.671979)},
{00617,(18.445147,-66.559696)},
{00622,(17.991245,-67.153993)},
{00623,(18.083361,-67.153897)},
{00624,(18.064919,-66.716683)},
{00627,(18.412600,-66.863926)},
{00631,(18.190607,-66.832041)},
... goes on and on...
{99922,(55.307528,-133.046815)},
{99923,(56.002315,-130.041026)},
{99925,(55.550204,-132.945933)},
{99926,(55.138352,-131.470424)},
{99927,(56.239062,-133.457924)},
{99929,(56.370751,-131.693301)}}; // total is about 33100 lines

    }
}

@jcouv commented on Wed Sep 20 2017

I'm able to repro this. The program compiles fine, but it overflows when run.

The strange thing is that decompiling the static constructor shows that it only expects to use very little IL stack (.maxstack 4 from debug compilation):

.method private hidebysig specialname rtspecialname static 
        void  .cctor() cil managed
{
  // Code size       1160053 (0x11b375)
  .maxstack  4
  .locals init (class [mscorlib]System.Collections.Generic.Dictionary`2<int32,valuetype [mscorlib]System.ValueTuple`2<float64,float64>> V_0)
  IL_0000:  newobj     instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,valuetype [mscorlib]System.ValueTuple`2<float64,float64>>::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ldc.i4     0x259
  IL_000c:  ldc.r8     18.180554999999998
  IL_0015:  ldc.r8     -66.749960999999999
  IL_001e:  newobj     instance void valuetype [mscorlib]System.ValueTuple`2<float64,float64>::.ctor(!0,
                                                                                                     !1)
  IL_0023:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,valuetype [mscorlib]System.ValueTuple`2<float64,float64>>::Add(!0,
                                                                                                                                                                  !1)
  IL_0028:  nop
  IL_0029:  ldloc.0
  IL_002a:  ldc.i4     0x25a
  IL_002f:  ldc.r8     18.361944999999999
  IL_0038:  ldc.r8     -67.175596999999996
  IL_0041:  newobj     instance void valuetype [mscorlib]System.ValueTuple`2<float64,float64>::.ctor(!0,
                                                                                                     !1)
  IL_0046:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,valuetype [mscorlib]System.ValueTuple`2<float64,float64>>::Add(!0,
                                                                                                                                                                  !1)
  IL_004b:  nop
  IL_004c:  ldloc.0
  IL_004d:  ldc.i4     0x25b
  IL_0052:  ldc.r8     18.455183000000002
  IL_005b:  ldc.r8     -67.119887000000006
  IL_0064:  newobj     instance void valuetype [mscorlib]System.ValueTuple`2<float64,float64>::.ctor(!0,
                                                                                                     !1)
  IL_0069:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,valuetype [mscorlib]System.ValueTuple`2<float64,float64>>::Add(!0,
                                                                                                                                                                  !1)
  IL_006e:  nop
  IL_006f:  ldloc.0
  IL_0070:  ldc.i4     0x25e
  IL_0075:  ldc.r8     18.158345000000001
  IL_007e:  ldc.r8     -66.932911000000004
  IL_0087:  newobj     instance void valuetype [mscorlib]System.ValueTuple`2<float64,float64>::.ctor(!0,
                                                                                                     !1)
  IL_008c:  callvirt   instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32,valuetype [mscorlib]System.ValueTuple`2<float64,float64>>::Add(!0,
                                                                                                                                                                  !1)

               ... repeats ...

I've tested this with debug build and also optimized build (/o+ compiler option), but both overflow at runtime.


category:correctness
theme:large-methods
skill-level:expert
cost:medium

Metadata

Metadata

Assignees

Labels

JitUntriagedCLR JIT issues needing additional triagearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIbugin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions