堆栈溢出错误可为空的数字类型c#

Posted

技术标签:

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

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

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

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

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

using System.Collections.Generic;
    using System;

    namespace ***
    
        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 方法。 我认为问题的目的是关于为什么当有很多行时你会得到***。这不是愚蠢的问题。因为 OP 已经知道如何使用循环,这是出于学习目的。 我刚刚对此进行了测试,Main 方法中的第一行运行良好。第二个无法编译,因此您需要提供更多信息才能弄清楚发生了什么。 @juharr 它确实有一个无参数的构造函数。它有Count,因为它继承自基类。 @Servy 我说的是new CreateCommands() 的第二行。 【参考方案1】:

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

在调试模式下为每个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。因此,这里的 *** 异常是一个错误,因为 JIT 没有正确删除堆栈条目。你尝试过哪些 JITters?

【讨论】:

只是标准。还在框架的 V4、4.5 和 4.6 中尝试过。

以上是关于堆栈溢出错误可为空的数字类型c#的主要内容,如果未能解决你的问题,请参考以下文章

缓冲区溢出及堆栈/堆操纵

Java分治算法堆栈溢出错误

用 C 语言编写一个程序,该程序使用递归来确定一个数字是不是为素数。大量出现堆栈溢出错误

怎么防止堆栈溢出

如何修复 Lisp 中的堆栈溢出错误

C# 捕获堆栈溢出异常