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.
@jcouv FYI
@andras-ferencz Those links appear to point to empty documents.
I'm able to see the repro file. The code causing stack overflow looks like this:
```C#
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
{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
}
}
```
I've been working my way through these geocoordinate positions, and so far I've found three gold bars buried after checking the first five locations, in one case barely escaping an angry farmer with a shotgun. One was in the alley behind a house (in a loosely filled pothole), one was dangerously close to a highway, and one was in the middle of a shooting range near a police academy. Can I please get community help checking out the rest? I'll be happy to share half the value of any gold bars you find.
Here are the ones I've already checked:
{97227,(45.543386,-122.678100)},
{97229,(45.551031,-122.809275)},
{97230,(45.557757,-122.505268)},
{97231,(45.687629,-122.824209)},
{97232,(45.528929,-122.643927)},
</justkidding>
@andras-ferencz Just for clarification, does the stack overflow that you describe occur (1) when you run that program, or (2) when you compile it? I assume it's the former case.
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 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.
From discussion with @VSadov, we think the IL is correct and does not mandate much stack usage. So this issue is most likely caused by JIT behavior. I will move the issue to the coreCLR repo.
Issue moved to dotnet/coreclr #14103 via ZenHub
Most helpful comment
I've been working my way through these geocoordinate positions, and so far I've found three gold bars buried after checking the first five locations, in one case barely escaping an angry farmer with a shotgun. One was in the alley behind a house (in a loosely filled pothole), one was dangerously close to a highway, and one was in the middle of a shooting range near a police academy. Can I please get community help checking out the rest? I'll be happy to share half the value of any gold bars you find.
Here are the ones I've already checked:
</justkidding>