我从ASP.NET应用程序返回的堆栈跟踪,从ArgumentNullException生成,给人的印象是下面代码的最后一行发生错误。据我所知,这是不可能的,但如果JIT优化了对Bar
的调用,这将导致不同的堆栈跟踪,它将解释所有。我肯定知道它不是c#编译器,因为CIL看起来像我期望的那样。是否有可能JIT编译器删除了对Bar的调用?
c#4,.NET 4.0.30319.1,ASP.NET 4.0.30319.1
修改 我应该提到这是一个发布配置,Optimize code = on,Debug Info = pdb-only。
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...
}
答案 0 :(得分:4)
根据http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx,如果JITter内联一个方法调用,它确实会在堆栈跟踪中折叠。如果你不想让它内联(这可能不是一个好主意),你可以使用
[MethodImpl(MethodImplOptions.NoInlining)]
关于方法。对于exe,您还可以使用INI文件告诉JITter生成跟踪信息(在链接页面的底部),但我不确定这对ASP.NET应用程序有何用处。
答案 1 :(得分:2)
我从未见过JIT删除方法调用,只是内联它。通常,它会删除未使用的局部变量,但我相当肯定JIT无法静态分析调用方法的所有副作用,因此我认为它不会删除方法调用。
我的猜测是将空值传递给在CreateHiddenField
内调用的方法,该方法恰好也有一个参数value
。由于默认情况下在发布模式下启用了内联,因此您无法真正信任堆栈跟踪(或发生异常的假定行号)。机会是你的问题在于CreateHiddenField
或更深入到不可见的堆栈中。 :)
您可以禁用优化以更好地了解堆栈跟踪。 MSDN has some instructions here