Возникнет ли исключение Stackoverflow с использованием одного метода в c#? - PullRequest
2 голосов
/ 10 января 2020

Исключение Stackoverflow возникает, когда метод вызывается рекурсивно (бесконечное число раз) (для каждого рекурсивного вызова выделяются разные кадры стека, в этом случае используются несколько кадров стека). Как мы знаем, кадр стека выделяется для каждого вызова метода. Можно ли переполнить стек одним методом (используя один кадр стека).

1 Ответ

4 голосов
/ 10 января 2020

можно переполнить стек одним методом

Конечно:

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

Переполнение стека происходит, когда стек полностью используется. Есть несколько способов сделать это; рекурсия - это только один из них. stackalloc создает указатель на блок памяти в текущем стековом кадре (или, в более позднем случае, на охват), расширяющий текущий стековый кадр; это будет концептуально исправлено (хотя на самом деле это просто означает изменение одного числа) при возврате (или throw, et c) из метода, который его выделил.


Другим способом было бы создать абсурдно тип значения с завышенным размером:

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