2013-04-11 11 views
5

スタックトレースASP.NETアプリケーションから返されるArgumentNullExceptionから生成されたトレースは、以下のコードの最後の行にエラーが発生しているという印象を与えます。私が見る限り、これは不可能ですが、JITがBarへの呼び出しを最適化すると、スタックトレースが異なるため、すべて説明できます。私は確かにそのC#コンパイラではないと知っている、CILは私が期待するように見える。 JITコンパイラがBarへのコールを削除した可能性はありますか?.NET JITコンパイラはメソッド呼び出しを最適化しますか?

のC#4、.NET 4.0.30319.1、ASP.NET 4.0.30319.1

編集:私は、デバッグ情報= PDB専用に=これは、最適化コードで、リリース構成で言及している必要があります

Stack Trace: 

[ArgumentNullException: Value cannot be null. Parameter name: value] 
CreateHiddenField(HtmlTextWriter tr, String name, String value) in Foo.cs:129 
Foo(IHttpContext context, HtmlTextWriter writer) in Foo.cs:106 

private static void Foo(IHttpContext context, HtmlTextWriter writer) 
{ // line 103 
    Bar(writer, AuthorizationServerResponseDetailsHttpRequestParser.RequestSAMLFieldName, context); 
    Bar(writer, AuthorizationServerResponseDetailsHttpRequestParser.RequestTargetFieldName, context); 
    // line 106 - blank line in source code. 
    CreateHiddenField(tr, name, string.Empty); // looks like its here 
} 

private static void Bar(HtmlTextWriter tr,string name, IHttpContext context) 
{ // line 116 
    #region Sanitation 
    if (tr == null) { throw new System.ArgumentNullException("tr"); } 
    if (name == null) { throw new System.ArgumentNullException("name"); } 
    if (context == null) { throw new System.ArgumentNullException("context"); } 
    #endregion 

    CreateHiddenField(tr, name, context.RequestQueryString(name)); 
} 

private static void CreateHiddenField(HtmlTextWriter tr, string name, string value) 
{ // line 127 
    #region Sanitation 
    if (tr == null) { throw new System.ArgumentNullException("tr"); } 
    if (name == null) { throw new System.ArgumentNullException("name"); } 
    if (value == null) { throw new System.ArgumentNullException("value"); } 
    #endregion 

    // payload... 
} 
+1

スタックトレースを提供できますか? JITは、スタックトレースから「消滅」する可能性のある要件を満たす場合、メソッドをインライン展開できます。最初のコードブロックに – Joshua

+0

があります。名前空間/ファイル名を削除して読みやすくしました。 – jasper

+1

あなたはそれがとても小さいので、スタックトレースではないと思います。私の推測では、それはインライン化されていますが、コンパイラが '適切な'スタックトレースを保持するコードを発行しているかどうかはわかりません。スタックトレースには行番号またはバイトオフセットが付いていますか? – Joshua

答えて

4

ジッタがメソッド呼び出しをインライン化した場合http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspxによると、それは確かにスタックトレースに崩壊されます。インライン化したくない場合は、

[MethodImpl(MethodImplOptions.NoInlining)] 

を使用することができます。 exeでは、INIファイルを使用してJITterに(リンク先ページの下部にある)トラッキング情報を生成するよう指示することもできますが、ASP.NETアプリケーションでどのように動作するかはわかりません。

+0

これはまさに私が探していたものですが、私はそれを見つけることができませんでした。 – Joshua

+0

完璧。 URLは疑わしいものを確認しますが、検索したときにその記事のようなものは見つかりませんでした。 – jasper

2

私は、JITがメソッド呼び出しを削除したことを見たことはありません。多くの場合、未使用のローカル変数は削除されますが、JITではすべての副作用をメソッド呼び出しから静的に解析できないことがわかります。したがって、メソッド呼び出しを削除するとは思われません。

私の推測では、valueというパラメータを持つCreateHiddenField内で呼び出されたメソッドにnull値が渡されていると思います。リリースモードでは、デフォルトでインライン展開が有効になっているため、スタックトレース(または例外が発生した場所の行番号)を実際に信頼することはできません。あなたの問題はCreateHiddenFieldの中にあるか、見えないスタックの深いところにある可能性があります。 :)

スタックトレースのより良い考え方を得るために最適化を無効にすることができます。 MSDN has some instructions here

関連する問題