【问题标题】:Stack overflow error nullable number types c#堆栈溢出错误可为空的数字类型c#
【发布时间】:2017-04-20 02:14:58
【问题描述】:

我有一个导致堆栈溢出异常的代码的简单示例,我想知道这是一个常见问题还是某种错误。

我正在使用控制台应用程序来生成一些数据。它将大约 20000 个对象添加到集合中。有些字段可以为空。如果我让他们布尔?那么它可以工作,但如果我将其中几个(如我在示例代码中所做的那样)更改为十进制?然后它抛出异常。

它也只在我物理添加 20000 Add(... 行时才会这样做。如果我在循环中这样做,那么它工作正常(这也在示例中)。

对代码示例的长度表示歉意。任何帮助将不胜感激。

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
        }
    }

【问题讨论】:

  • 那不会编译,因为没有CreateCommands 类。如果您的意思是 new CreateCommand 没有无参数构造函数,也没有定义 Count 方法。
  • 我认为问题的目的是关于为什么当有很多行时你会得到stackoverflow。这不是愚蠢的问题。因为 OP 已经知道如何使用循环,这是出于学习目的。
  • 我刚刚对此进行了测试,Main 方法中的第一行运行良好。第二个无法编译,因此您需要提供更多信息才能弄清楚发生了什么。
  • @juharr 它确实有一个无参数的构造函数。它有Count,因为它继承自基类。
  • @Servy 我说的是new CreateCommands() 的第二行。

标签: c# .net collections stack overflow


【解决方案1】:

本质上,堆栈的大小是有限的,因此在没有无限循环的情况下,您也可能会遇到StackOverflowException

在调试模式下为每个Add-call 生成以下 IL 代码:

.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)

(每次迭代的行号当然不同,前两个声明不再重复)

在这段代码中,堆栈应该保持相同大小,maxstack 计算为 15。因此,这里的 StackOverflow 异常是一个错误,因为 JIT 没有正确删除堆栈条目。你尝试过哪些 JITters?

【讨论】:

  • 只是标准。还在框架的 V4、4.5 和 4.6 中尝试过。
猜你喜欢
  • 1970-01-01
  • 2016-01-17
  • 2016-11-11
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 2014-01-26
  • 2019-02-16
  • 2011-09-10
相关资源
最近更新 更多