8

再帰を使用せずにスタック オーバーフロー例外をスローするにはどうすればよいですか?

4

10 に答える 10

20

誰もそれについて言及していないので:

throw new System.StackOverflowException();

テストまたはフォールト注入を行うときにこれを行うことがあります。

于 2009-10-17T23:45:10.757 に答える
17

ENORMOUS 配列をローカル変数として宣言します。

于 2009-10-17T23:28:43.850 に答える
12

十分な数のメソッドを呼び出すと、いつでもスタック オーバーフローが発生する可能性があります。ただし、再帰を使用せずにスタック オーバーフロー エラーが発生した場合は、自分のやり方を再考することをお勧めします。無限ループでは大量のメソッドを呼び出すため、再帰を使用すると非常に簡単です。

于 2009-10-17T23:29:06.423 に答える
7

以下は Windows に適用されますが、ほとんどの OS はこれを同様の方法で実装します。

簡単に言えば、最後のガード ページに触れると、スローされます。

タイプ EXCEPTION_STACK_OVERFLOW (C00000FD) の例外は、アプリケーションがPAGE_GUARD保護フラグがマークされているスタックの一番下のページに触れたときに発生し、スタックを拡大する (もう 1 ページをコミットする) 余地がありません。「スタックをトラップする方法」を参照してください。 Visual C++ アプリケーションでのオーバーフロー
これが発生する典型的なケースは、スタック上の多くの関数フレームの結果 (つまり、制御不能な再帰) としてスタックが大きくなった場合です。オブジェクト) または明示的にスタックから割り当てます_alloca
例外を発生させるもう 1 つの方法は、単に意図的にガード ページに触れることです。そのページを指すポインターを逆参照することによって。これは、変数の初期化のバグが原因で発生する可能性があります。

入力が非常に深いネスティング レベルを引き起こす場合、有効な実行パスでスタック オーバーフローが発生する可能性があります。たとえば、「SQL Server で IN または NOT IN 句内に多数の引数を含むクエリを実行すると、スタック オーバーフローが発生する」を参照してください。

于 2009-10-18T00:04:06.483 に答える
2

まだ返されていないすべてのメソッド呼び出しは、スタック スペースをいくらか消費します。(より多くのローカル変数を持つメソッドは、より多くのスペースを消費します。) 非常に深い呼び出しスタックは、スタック オーバーフローを引き起こす可能性があります。

メモリが限られているシステム (モバイル デバイスなど) では、スタック スペースがあまりなく、すぐに不足することに注意してください。

于 2009-10-17T23:32:49.490 に答える
2

簡単な答え: 内部オブジェクトを呼び出すオブジェクトがある場合、スタック トレースを 1 増やします。したがって、1000 個のオブジェクトが互いにネストされており、それぞれが内部オブジェクトを呼び出している場合、最終的にスタック オーバーフローが発生します。

ネストされたイテレータを使用して素数を生成する方法のデモを次に示します。

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();

            IEnumerator<int> primes = p.AllPrimes().GetEnumerator();
            int numberOfPrimes = 1000;
            for (int i = 0; i <= numberOfPrimes; i++)
            {
                primes.MoveNext();
                if (i % 1000 == 0)
                {
                    Console.WriteLine(primes.Current);
                }
            }
            Console.ReadKey(true);
        }

        IEnumerable<int> FilterDivisors(IEnumerator<int> seq, int num)
        {
            while (true)
            {
                int current = seq.Current;
                if (current % num != 0)
                {
                    yield return current;
                }
                seq.MoveNext();
            }
        }

        IEnumerable<int> AllIntegers()
        {
            int i = 2;
            while (true)
            {
                yield return i++;
            }
        }

        IEnumerable<int> AllPrimes()
        {
            IEnumerator<int> nums = AllIntegers().GetEnumerator();
            while (true)
            {
                nums.MoveNext();
                int prime = nums.Current;
                yield return prime;

                // nested iterator makes a big boom     
                nums = FilterDivisors(nums, prime).GetEnumerator();
            }
        }
    }
}

再帰はありませんが、プログラムは約 150,000 素数の後でスタック オーバーフロー例外をスローします。

于 2009-10-17T23:53:00.027 に答える
1

合理的な標準ライブラリを使用して C++ について話している場合、これはうまくいくと思います。

while (true) {
    alloca(1024 * 1024); // arbitrary - 1M per iteration.
}

allocaの詳細。

于 2009-10-17T23:49:49.877 に答える
0
int main()
{
  //something on the stack
  int foo = 0;
  for (
    //pointer to an address on the stack
    int* p = &foo;
    //forever
    ;
    //ever lower on the stack (assuming that the stack grows downwards)
    --p)
  {
    //write to the stack
    *p = 42;
  }
}
于 2009-10-18T00:29:16.193 に答える
0

スタックに数バイトを割り当てることもできます。

static void Main(string[] args)
{
    Span<byte> b = stackalloc byte[1024 * 1024 * 1024]; // Process is terminating due to StackOverflowException.
}
于 2019-10-23T10:55:24.207 に答える
-1

StackOverflowException を作成する最も簡単な方法は次のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            SomeClass instance = new SomeClass();
            string name = instance.Name;
        }
    }

    public class SomeClass
    {
        public string Name
        {
            get
            {
                return Name;
            }
        }
    }
}
于 2009-10-18T00:11:12.767 に答える