4

これが非常に漠然としていることはわかっていますが、これが私が収集できるすべてです。誰かがこれがどのように起こっているのかについての洞察を持っていることを願っています.

Visual Studio 2012で構築されたWin 7 64ビットマシンで実行している64ビットプログラムがあります。

別のプロジェクト (dll としてコンパイル) にあるクラスを使用します。そのクラスには、スタック オーバーフローを引き起こす可能性のあるバグのある反復子があります。そのバグのある反復子を呼び出す操作は、タスクを通じて呼び出されます。

したがって、私のプログラムでは、コードは次のようになります。

new Task(()=>{
try
{
    DoWork(); //<-- buggy iterator is called inside
}
catch (Exception ex)
{
    //Exception reported to user
}
}).Start();

コードは毎回同じデータに対して実行され、確率変数や GUID 生成が含まれていないため、毎回同じ出力が生成されます。

ほとんどの場合、不明なモジュールで発生する StackOverflowExceptionでクラッシュします (正確に発生する場所は知っていますが)。その場合、オーバーフローが発生したコード内のポイントを表示できず、try-catch ブロックは何もしません! プログラムの実行を続行できません (デバッグなしで実行すると、「プログラムを閉じる必要がありました。ソリューションをオンラインで確認してください」というシステム ウィンドウが表示されます)。

現在、例外をキャッチすることがあります (例外を引き起こしたコード内の正しい場所が表示されます)。これはランダムですが、タスクをより頻繁に中断すると (作業中にタスクにランダムにブレークポイントを挿入するなど)、より多く発生するようです。

しかし、まだ申請を続行できません。例外は、StackOverflowException をキャッチするはずの try-catch ブロック内で発生しますが (StackOverflowException は例外に含まれているため、キャッチする必要があります。C# では両方をキャッチできず、SOE が既に E に含まれていることを明示的に伝えます)。

try-catch ブロック内で意図的にスタック オーバーフローを発生させる小さなプログラムを作成しようとしましたが、それを正しく処理する代わりに、 「プログラムを閉じてオンラインでソリューションを確認する必要がありました」というシステム ウィンドウも表示されました。コードは次のとおりです。

    private bool Overflow()
    {
        return Overflow();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        try { Overflow();}
        catch (StackOverflowException ex) { }
    }

したがって、いくつか質問があります。

質問1:

StackOverflowExceptions をキャッチすることは可能ですか? どうすればいいのですか?

質問2:

dll (同じソリューション内の他のプロジェクト) 内でスタック オーバーフローが発生した場合、VS 2012 デバッガーが "不明なモジュール" と見なす原因は何ですか?

質問 3:

部族の楽器を使って奇妙な魔法のダンスを踊ると、それがあまり頻繁に行われないのはなぜですか? (つまり、進行中のプログラムをランダムに壊すことを意味します)

全体として、何が起こっているのですか?

前もって感謝します

4

2 に答える 2

1

実際のスタック オーバーフロー例外をキャッチすることは許可されていないため、機能しません。

このディスカッションも参照してください。

2 番目の質問には、「プログラムがめちゃくちゃだ」と言う以外には答えられません。

3 番目の質問: 別のスレッドで実行されているため、実行されたコードの量は、プログラムをいつ中断するかによって異なります。これの真相を突き止める唯一の方法は、退屈な行ごとのデバッグ、または大量の Debug.WriteLine() を使用することだと思います。

于 2013-04-09T08:38:26.450 に答える
0

1) .NET Framework バージョン 2.0 以降では、StackOverflowException オブジェクトを try-catch ブロックでキャッチできず、対応するプロセスが既定で終了します。したがって、スタック オーバーフローを検出して防止するコードを記述することをお勧めします。たとえば、アプリケーションが再帰に依存している場合は、カウンターまたは状態条件を使用して再帰ループを終了します。共通言語ランタイム (CLR) をホストするアプリケーションは、CLR がスタック オーバーフロー例外が発生したアプリケーション ドメインをアンロードし、対応するプロセスを続行させるように指定できることに注意してください。詳細については、「ICLRPolicyManager インターフェイスとホスティングの概要」を参照してください。( http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx )

于 2013-04-09T08:39:19.737 に答える