【问题标题】:Will the Stackoverflow exception occur by using single method in c#?在c#中使用单一方法会发生Stackoverflow异常吗?
【发布时间】:2020-04-27 19:20:06
【问题描述】:

当一个方法被递归调用(无限次)时会发生 Stackoverflow 异常(每个递归调用分配不同的堆栈帧,在这种情况下使用多个堆栈帧)。众所周知,每个方法调用都会分配一个堆栈帧。堆栈是否可以使用单一方法(使用单个堆栈帧)溢出。

【问题讨论】:

  • “为每个方法分配一个超级堆栈帧” - 这是不正确的。为每个方法 call 分配一个堆栈帧。溢出的最常见原因是在没有合适的中断条件的情况下调用自身的方法。
  • “当一个方法被递归调用时(无限次)”——它不必是无限的——只是“太多”
  • 好酷,很多次

标签: c# stack stack-overflow


【解决方案1】:

使用单一方法可以溢出堆栈吗

当然:

static unsafe void Main()
{
    for(int i = 0; i < 50; i++)
    {
        // fails on i=18 for me
        long* ptr = stackalloc long[10 * 1024];
    }
}

当堆栈被完全消耗时会发生堆栈溢出。有多种方法可以做到这一点;递归只是其中之一。 stackalloc 在当前堆栈帧处创建一个指向(或最近:跨越)内存块的指针,扩展当前堆栈帧;当您从分配它的方法返回(或抛出等)时,它将在概念上被回收(尽管实际上,这只是意味着更改单个数字)。


另一种方法是创建一个荒谬的超大值类型:

static class P
{
    static void Main() => Foo();
    static void Foo() => Bar(default);
    static void Bar(FatStruct2097152‬ a) => Console.WriteLine(a);
}

struct FatStruct64 {
    private long a, b, c, d, e, f, g, h;
}
struct FatStruct512 {
    private FatStruct64 a, b, c, d, e, f, g, h;
}
struct FatStruct4096 {
    private FatStruct512 a, b, c, d, e, f, g, h;
}
struct FatStruct32768 {
    private FatStruct4096 a, b, c, d, e, f, g, h;
}
struct FatStruct262144 {
    private FatStruct32768 a, b, c, d, e, f, g, h;
}
struct FatStruct2097152 {
    private FatStruct262144 a, b, c, d, e, f, g, h;
}

【讨论】:

  • How to change stack size for a .NET program? 可用于让不太引人注目(不是unsafe)的方式也足够快地实现它。
  • 马克-很好!我不记得struct 的大小是否有限制,以及是否有一个与默认堆栈大小相差多远,所以尽管您无论如何都需要缩小堆栈...但现在懒得尝试:)跨度>
  • 我对这种可憎的东西(当然是 FatStruct)的反应基本上是this scene from Jurassic Park?
  • 所以现在栈内存是栈帧内存的集合。如果调用了一个新的方法调用了一个栈帧分配,这个实际意义是什么?(是把下一个块分配给新的方法调用?)
  • @NikhilChitneni 堆栈帧不是这样“分配”的——堆栈只是一块连续的内存;没有块——它只是一块虚拟内存;方法调用只需占用目标和参数所需的空间,(一定数量的)簿记空间,(一定数量的空间)用于方法声明的局部变量,然后它只是递增(从技术上讲,递减 -堆栈向下增长,因为原因)指向该空间内当前语义框架的指针
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多