StackTrace/StackFrame不会在生产环境中返回预期信息

ahm*_*md0 6 c# asp.net debugging stack-trace visual-studio-debugging

我在ASP.NET Web应用程序中使用以下方法来接收异常的堆栈跟踪:

public static void getStackTraceInfo(System.Diagnostics.StackTrace trace)
{
    for (int i = 0; i < trace.FrameCount; i++)
    {
        int nLine = trace.GetFrame(i).GetFileLineNumber();
        int nCol = trace.GetFrame(i).GetFileColumnNumber();
        string methodName = trace.GetFrame(i).GetMethod().Name;
    }
}

try
{
}
catch(Exception ex)
{
    getStackTraceInfo(new System.Diagnostics.StackTrace(ex, true));
}
Run Code Online (Sandbox Code Playgroud)

如果我在Visual Studio 2010开发环境中运行它,它会为我提供完整的行/列/方法名称信息,但在IIS上的生产环境中,它将返回所有0和方法名称为空字符串.

我是否还需要做一些特殊的事情才能使它在IIS上运行?

Eri*_*ert 32

如果我在Visual Studio 2010开发环境中运行它,它会为我提供完整的行/列/方法名称信息,但在IIS上的生产环境中,它将返回所有0和方法名称为空字符串.

正确.仔细阅读该类型的名称; 这Diagnostics很重要.该命名空间中的类型用于诊断调试环境中的问题.

我是否还需要做一些特殊的事情才能使它在IIS上运行?

没有; 您不需要在生产中使用诊断工具.

如果由于某种原因您希望在生产环境中使用诊断工具,则至少需要将PDB文件推送到生产环境.这可能是一件危险且愚蠢的事情,我们将在下面看到.我建议你不要这样做.

你没有问过的一些问题:

我应该使用什么工具来获取生产环境中的呼叫者信息?

如果需要获取方法调用的行号等,您可能应该使用的工具是CallerLineNumberC#5.0中的新属性和相关属性.这是一个很好的博客:

http://blog.slaks.net/2011/10/subtleties-of-c-5s-new-callerlinenumber.html

如果您需要获取有关异常的堆栈跟踪的信息,您所看到的就是您所获得的.

在调试环境中,StackTrace对象是否保证堆栈跟踪告诉我当前调用的来源

不会.堆栈跟踪不会告诉您首先来自哪里.堆栈跟踪会告诉您下一步的位置.这很有用,因为你来自哪里和下一步之间通常有很强的相关性; 通常你会回到你来自的地方.

但事实并非如此.CLR有时可以在不知道您来自何处的情况下找出下一步的位置,在这种情况下,堆栈跟踪不包含您需要的信息.

例如,尾调用优化可以从堆栈中删除帧.内联优化可以使对方法的调用看起来像调用方法的一部分.C#5中的异步工作流完全离婚"你来自哪里"和"你下一步去哪里"; 异步方法的堆栈跟踪在await告诉您下一个之后的位置后重新开始await,而不是在第一个之前进入方法的方式await.

堆栈跟踪不可靠,因此不要依赖它们.仅将它们用作诊断辅助工具.

为什么在ASP中公开诊断信息特别危险?

因为攻击者会通过向其投掷"特殊"输入来尝试使服务器失败.如果这会让服务器失灵,那么攻击者会很高兴.如果它使服务器保持运行但向攻击者泄漏有关源代码的信息,那就更好了.现在,他们有更多信息可用于发动更复杂的攻击.

ASP服务器应该在生产环境中尽可能少地获取诊断信息.您在该生产环境中的调试信息越少,您犯错的可能性就越小,并将您的实施细节暴露给攻击者.

  • @ ahmd0:当我告诉人们堆栈痕迹的真相时,我得到的阻力是惊人的.堆栈跟踪包含*返回地址*,它不必是*调用者*的地址.它大部分时间都是,但它不一定是,并且在某些情况下它不是.请记住,堆栈的目的是继续*的实现,并且继续是关于*future*的定义信息,而不是*过去的*.如果你有时可以从延续中推断出过去的信息,那很好,但这不是它的目的*,所以你不能依赖它. (18认同)
  • @KenKin:不,我认为这是因为大多数人被教导*堆栈跟踪"告诉你你来自哪里",并且因为大多数开发人员看到的99.99%的代码都是*true*,他们相信它.如果认识到堆栈跟踪只告诉你你来自哪里*因为你回到那里*而不是*因为这是它的设计目的*,这可能会非常令人不安. (4认同)
  • 当然也没有要求继续通过堆栈来实现.正如我上面提到的,通过委托和上下文的组合来实现异步任务的继续; 没有涉及堆栈,因此知道任务的继续不会告诉你关于如何开始任务的任何事情. (2认同)
  • @ ahmd0:许多简单的堆栈跟踪确实*发生*来自你来自哪里,如果它与你要去的地方相同.Eric提到`async`代码特别将这两者分开; [此MSDN文章](http://msdn.microsoft.com/en-us/magazine/jj891052.aspx)详细介绍. (2认同)