私はそれはそれは(まだ)が発生し、なぜ私は知らない
を起こってからそれを停止する方法を知っています。そして、あなたは実際に.Net BCLか、おそらくはJITのいずれかでバグを発見したようです。
私はちょうどMyButton_Click_Aux
メソッドのすべての行をコメントアウトし、次にそれらを1つずつ戻し始めました。
static intからvolatile
を削除すると、StackOverflowException
が返されなくなります。今
明らかにメモリバリアとは何かが問題の原因となっている理由は...研究する - おそらく何らかの形で自分自身を呼び出すためのMyButton_Click_Aux
方法を強制的に...
UPDATE
わかりましたので、他の人NET 3.5は問題ではないことが判明しています。
私もこれらのコメントは、それに関連して.Nt 4を使用しています:私が言ったように
は、揮発性のオフを取り、それが動作します。あなたは背中の揮発を入れて、削除する場合
同様に、試しては最終的に、それはまた、作品/:
private static void MyButton_Click_Aux()
{
//try { /*remove because stack overflows without*/ }
//finally
//{
var myLogData = new ArrayList();
myLogData.Add(reportCount);
//myLogData.Add("method MyButtonClickAux");
//Log(myLogData);
//}
}
試してみるが、最終的には/とき初期化されていないreportCount
とは何かだった場合、私も疑問に思いましたしかし、それをゼロに初期化すれば、違いはありません。私は今、ILで探しています
- それは参加するためにいくつかのASMのチャップスを持つ人を必要とするかもしれませんが...私が言うように、これは本当にの分析を必要とする予定です
最終更新実際に何が起こっているのかを理解するためのJIT出力と、アセンブラを分析するのが楽しいと感じている間に、おそらくMicrosoftの誰かの仕事だと感じています。それは非常に狭い状況のようです。
私はリリースビルドに移行して、分析のためにすべてのILノイズ(nopsなど)を取り除きました。
しかし、これは診断に複雑な影響を与えました。私はそれを持っていると思ったが、しなかった - しかし、今私はそれが何であるか知っている。揮発性としてint型で
private static void MyButton_Click_Aux()
{
try { }
finally
{
var myLogData = new ArrayList();
Console.WriteLine(reportCount);
//myLogData.Add("method MyButtonClickAux");
//Log(myLogData);
}
}
:
私はこのコードを試してみました。それは間違いなく実行されます。ここではILだ: .maxstack 1
L_0000: leave.s L_0015
L_0002: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
L_0007: pop
L_0008: volatile.
L_000a: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) WindowsFormsApplication1.Form1::reportCount
L_000f: call void [mscorlib]System.Console::WriteLine(int32)
L_0014: endfinally
L_0015: ret
.try L_0000 to L_0002 finally handler L_0002 to L_0015
その後、我々は再びエラーを取得するために必要な最小限のコードを見て:
private static void MyButton_Click_Aux()
{
try { }
finally
{
var myLogData = new ArrayList();
myLogData.Add(reportCount);
}
}
そして、それはILます:
.maxstack 2
.locals init (
[0] class [mscorlib]System.Collections.ArrayList myLogData)
L_0000: leave.s L_001c
L_0002: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
L_0007: stloc.0
L_0008: ldloc.0
L_0009: volatile.
L_000b: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) WindowsFormsApplication1.Form1::reportCount
L_0010: box int32
L_0015: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
L_001a: pop
L_001b: endfinally
L_001c: ret
.try L_0000 to L_0002 finally handler L_0002 to L_001c
違いは?まあ、揮発性のintのボクシングとバーチャルコール - 私が発見した2つです。だから私のセットアップこの2つのクラス:
public class DoesNothingBase
{
public void NonVirtualFooBox(object arg) { }
public void NonVirtualFooNonBox(int arg) { }
public virtual void FooBox(object arg) { }
public virtual void FooNonBox(int arg) { }
}
public class DoesNothing : DoesNothingBase
{
public override void FooBox(object arg) { }
public override void FooNonBox(int arg) { }
}
そして問題のある方法のこれらの4つのバージョンのそれぞれを試してみました:作品
try { }
finally
{
var doesNothing = new DoesNothing();
doesNothing.FooNonBox(reportCount);
}
。
try { }
finally
{
var doesNothing = new DoesNothing();
doesNothing.NonVirtualFooNonBox(reportCount);
}
これも機能します。
try { }
finally
{
var doesNothing = new DoesNothing();
doesNothing.FooBox(reportCount);
}
おっと - StackOverflowException
。
そして:再び
try { }
finally
{
var doesNothing = new DoesNothing();
doesNothing.NonVirtualFooBox(reportCount);
}
おっと! StackOverflowException
!
私はこれをさらに進めることができました - しかし、問題は明らかにtry/catchのfinallyブロックの内側にある揮発性intのボクシングによって引き起こされたと思います。問題ない。私はcatch節を追加し(そしてそこにコードを入れた)、問題はなかった。
それは私が推測する他の値の種類のボクシングにも適用できます。
したがって、.Net 4.0では、デバッグとリリースビルドの両方で要約すると、finallyブロック内の揮発性intのボクシングは、JITがスタックを満たす最後のコードを生成するように見えます。スタックトレースが単に「外部コード」を表示しているという事実も、この命題をサポートしています。
try/finallyによって生成されるコードのレイアウトやサイズによっては、必ずしも再現できない可能性もあります。これは、間違った場所に誤って生成された誤ったjmp
などと明らかに関係しており、最終的にスタックに1つ以上のプッシュコマンドを繰り返します。それが実際にボックス操作によって引き起こされているという考えは、率直に、魅力的です!
決勝最終更新
あなたは@Hasty Gが見つかっMS接続のバグ(さらに下に答える)を見れば - あなたがそこに見ること揮発性ブールのあるが、同様の方法でバグマニフェスト、 キャッチステートメント。
また、MSはこれをreproで入手した後に修正プログラムをキューイングしましたが、まだ7か月後に修正プログラムはありません。私はMS Connectのサポートとして以前に記録に残っているので、私はもう言わないだろう - 私は必要とは思わない!
決勝決勝決勝更新(23/02/2011)
それは固定されている - が、まだリリースされていません。 MS ConnectバグのMSチームからのお見積もり:
はい、修正されました。私たちは、修正プログラムをどのように配布するのが最適かを把握しています。これは4.5で修正されていますが、4.5リリース前にコード生成バグのバッチを修正したいと思っています。
"それゆえに.netのバグでなければなりません"おそらくそうではありません。 – jason
「MyButton_Click_Aux」のコードを投稿してください –
MyButton_Click_Auxにコードを含めてください。 –