C# 为什么在不同的呼叫号码上引发堆栈溢出异常?
考虑以下代码:C# 为什么在不同的呼叫号码上引发堆栈溢出异常?,c#,recursion,stack-overflow,C#,Recursion,Stack Overflow,考虑以下代码: private static int i = 0; static void Main(string[] args) { DoSomething(); Console.ReadLine(); } public static void DoSomething() { Console.WriteLine(i); ++i; DoSomething();
private static int i = 0;
static void Main(string[] args)
{
DoSomething();
Console.ReadLine();
}
public static void DoSomething()
{
Console.WriteLine(i);
++i;
DoSomething();
}
每次运行它时,我都会在I
变量的不同值上获得StackOverflowException
。例如160231620016071
这背后的原因是什么?这是C#编译器中的错误吗?您的堆栈大小不够大 您可以通过启动新线程并在构造函数中定义新的stacksize来增加默认stacksize:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication3
{
class Program
{
private static int i = 0;
static void Main(string[] args)
{
Thread T = new Thread(DoSomething, 100000000);
T.Start();
Console.ReadLine();
}
public static void DoSomething()
{
Console.WriteLine(i);
++i;
DoSomething();
}
}
}
Stackoverflow现在发生在150万个递归调用上。无界递归的行为由实现定义。实现定义意味着它可以做任何事情。程序可以随时终止(或永不终止)、抛出未处理的异常或其他任何情况。例如,编译为MSIL并在64位操作系统上运行,该程序对我来说永远不会终止。这是因为允许抖动将递归转换为循环,而64位抖动就是这样做的。询问它为什么以特定值终止没有实际意义,因为运行时被允许做任何事情。AFAIK,CLR不保证堆栈的最大深度。堆栈的最大深度是多少?这是我的观点-CLR不提供任何保证。那么:这是C#编译器中的一个bug吗?没有。但是16k真的非常的推动它。我有同样的例外在发布模式下执行同样的代码,数字是128800。。。这是80倍的解释。所以,运行时拥有完全的权限,可以停止并抛出异常,也可以继续重复。我不确定我是否真的将尾部调用描述为一个循环,但我想它传达了一个相同的信息,即堆栈的大小不够大,无法进行无限次的跳转(不包括尾部调用)