vb.netでStackOverflowの例外とは何ですか?
-
11-09-2019 - |
質問
私も自分のアプリケーションで、それの原因を知りません。それは何ですか?私は(クラスが別のファイルにあった)クラスの新しいインスタンスを作成しますが、最初の時点で私はそれがStackOverflowの例外をスローするメソッドを呼び出します。
誰かがジョンスキートをdownvoted場合、私は論理的にstackoverflowの例外をスローだと思う唯一のことは次のようになります。
しかし、真剣に、今、それは何ですか?私は、最初のクラスと同じファイル内の別のクラスを作成し、それは私のためのメソッドを呼び出すために使用することにより、その周りになっています。
解決
原則として、スタックオーバーフロー例外は、再帰の深さ(典型的に)固定されたスタックの限界を超えた再帰アルゴリズムによって引き起こされます。これは通常、アルゴリズムのバグの結果であるが、それはまた、あなたがあまりにも「深い」であることにアルゴリズムを適用しているデータ構造によって引き起こされることがあります。
ここでは(特段PLにおける)バギー再帰の簡単な例です。
function int length(list l) {
if (empty(l)) {
return 0;
} else {
return 1 + length(l); // should be 'return 1 + length(tail(l));
}
}
任意の非空のリストのための呼び出しの長さは、一般的なプログラミング言語でのスタックオーバーフローを与えるだろう。しかし、あなたはバグを修正した場合でも、長いリストのためのメソッドを呼び出すと、スタックオーバーフローを引き起こす可能性があります。
(あなたは言語...またはより厳密コンパイラ...末尾再帰の最適化をサポートして使用する場合は例外です。)
他のヒント
stackoverflowの例外を使用すると、割り当てられたスタックサイズを超えた場合、これは一般的に再帰的に呼び出すメソッドから発生し、決して残さない、それはまた、様々なあいまいなメソッドチェーンによって原因となる可能性があります。問題は、あなたはおそらく、オブジェクトに次の程度のものを持っている。
void MyMethod()
{
MyMethod();
}
の呼び出しが食べ、決して呼び出しが残っている必要があり、実行し、エントリポイントを終了したことがないので、使用するスタック領域を解放します。
P.S。 SO(これは基本であり、.NETに限定されない)問題の特定の例外にちなんで命名された、それは開発者のサイトのためだけの巧妙な名前です。
StackOverFlows例外は、彼らのような音を正確に何スタックオーバーフローです。あなたの方法での循環依存関係を持っているので、通常、これはあります。インスタンスメソッドのためにAがBを呼び出し、Bは、Aを呼び出すか、それがベースケースなしの再帰的方法であってもよい。
のコードを見ることなく、起こったが、スレッドがそのコールスタックをオーバーフローしたときにStackOverflowException
がスローされた理由を伝えることは不可能です。この方法は、任意の条件付きブレークは、このように無限再帰を作成せずに自分自身を再帰的に呼び出したときにこれが最も頻繁に発生します。各再帰が新しいスタックフレームを作成するので、無限再帰が理論的には、スタック・フレームの無限の数を作成することになり、私は用語「スタックオーバーフロー」はがちである理由あなたが今見ることができると確信しています。
スタックです。機能主な機能Aを呼び出し、呼び出し関数Bを機能し、そして、彼らは変数C、DとEを使用するのであれば、スタックは、その情報のすべてが含まれます。ただし、スタックはとても大きいです。関数Bは、関数Dを呼び出す関数をC、...などを呼び出すのであれば、ネストされた関数の数百に終わる、最終的には、スタックは、「オーバーフロー」します - 別の関数呼び出しを格納するのに十分なスペースがありません。
他の人が指摘しているように、これは通常、再帰関数で発生します。(その後、関数Bを呼び出す関数Bが関数Bを呼び出し、...) - 最終的には、スタックがオーバーフローします。あなたは、その再帰関数が呼び出されている場所を見つける必要があります、そしてそれは想定通りにするとき、なぜそれが再帰ループの外に破壊されていません。
もちろん、問題は、それがバグだらけの再帰的なアルゴリズムだということではないかもしれない - それだけで関数呼び出しの数は、スタックのサイズを超えている可能性があります。あなたのアルゴリズムは数百回の再帰関数を呼び出す可能性を秘めているのであれば、それはそれかもしれません。
これは、通常、その再帰呼び出しが終了したことがない関数の再帰呼び出しによって引き起こされます。あなたはいくつかの方法でこれを取得することがあります。一つの方法は、他の一般的なものは、それらのコンストラクタなどでお互いのいずれかを作成し、オブジェクトA及びBを作成して、ベースケースなし再帰アルゴリズムとすることができる。
私は、デバッガをステップ実行して見つけるお勧めします。)
私は最近のデータも同様に大量のソートに巨大な再帰関数を使用VB.NETへの古いVB6アプリケーションを移植しました。このアルゴリズムは大丈夫だったが、実行は一貫して、スタックオーバーフローエラーが発生しました。多くのあいた後、私はVBのコードの後ろに多くの魔法にやっていたことに気づい:簡単な型キャストは価格が付属しています。だから、(単一のコード行が2〜10の関数から呼び出すことができます...)再帰関数ではなく、型変数を使用しての遅延バインディングにあまりにも多くを頼った、これは巨大などの解析鋳物の量は、オーバーヘッドをもたらしました、明らかに、スタックオーバーフローを作りました。
TL; DR:使用DirectCast()と静的再帰関数に実行時にスタックのフラッディングからVBを防止するために(入力した変数)結合
。私はこの問題は私のlstEncounterを誤入力したことに気づい起こりました。私はC ++のクラスで学んだように、問題は基本的に同じパラメータで自身を呼び出す再帰的なアルゴリズムです。私はエラーを得た私の例:
Property Encounter(ByVal N As Integer)
Get
If N < lstEncounters.Count Then
Return Encounter(N)
Else
Return Nothing
End If
End Get
Set(value)
lstEncounters(N) = value
End Set
End Property
私はStackOverflowのエラーを持っていました。 私はその後、同じルーチンと呼ばれる再カウンタに1を追加したルーチンを使用していました。 私はstackoverflowのエラーを得たほぼすべての2500〜3000のループ。
:私はVB Expressを使用し、ルーチンを呼び出すDO ...ループを追加しました前:
Public Sub mainloop()
Dim cntr as integer
If cntr >= 5000 ( I just picked a number at random)
me.close ( I close the program)
... (This is where I would manipulate the cntr for diff
results)
cntr = cntr + 1 ( increment the cntr)
mainloop() (re call my loop)
End IF
End Sub
(私が前に言ったように、およそ2500から3000の後、私はStackOverflowのエラーになるだろう)。
AFTER:(これは最初に実行する場所)
Dim LoopCntr as integer
Do While LoopCntr <= 40000 (this my number.. Use your own number)
If LoopCntr > 40000 Then
Exit Do
End If
mainloop() (The mainloop() has not been changed just the method of calling it)
LoopCntr = LoopCntr + 1
Loop
me.close (When LoopCntr reaches max it closes the program)
タグ(Do..Loopを追加した後、私のプログラムは、 "StackOverflowの" なしで40000時間を走りました)