蛙蛙推荐:怎样调试asp.net黄页错

蛙蛙推荐:怎样调试asp.net黄页错
摘要:如果你的web应用莫名其妙的报了一个未处理异常,出现了一个黄色页面的错误,你都是如何来排错的?如果报错页面显示的调用栈上没有做任何log和trace,也没有对参数和全局变量做一些断言,你咋办?如果源码也不在你手上,你在给客户解决问题你咋办?

我们先来模拟问题,这是一个简单的页面,接受一个查询字符串,如果这个字符串能转换成整形,并且是偶数,就原样输出,如果是奇数,Page_Load方法里没有进行对handleInput方法的返回值进行是否为空的判断就直接调用ToUper的方法,所以当查询字符串为奇数的时候就会抛出未处理异常,出现大黄页,代码如下

using System;
using System.Web.UI;

namespace WebApplication1
{
    public partial class TestException : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                string input = Request.QueryString["id"];
                //这里没有判断handleInput方法的返回值
                Response.Write(handleInput(input).ToUpper());
            }
            catch (ArgumentNullException ane)
            {
                Response.Write(ane.Message);
                Response.End();
            }
            catch (ArgumentException ae)
            {
                Response.Write(ae.Message);
                Response.End();
            }
        }

        private static string handleInput(string input)
        {
            if (string.IsNullOrEmpty(input))
                throw new ArgumentNullException("input", "输入数据不能为空");

            int intInput;
            if (!int.TryParse(input, out intInput))
                throw new ArgumentException("输入数据不是整形", "input");

            return intInput %2 == 0 ? intInput.ToString() : null;
            //这里没有检查后置参数的值,导致该方法可返回无效值null。
        }
    }
}

有时候我们机器上有多个网站,每个网站使用不同的应用程序池,这就会有多个w3wp进程,我们得先确定我们的web应用的进程ID,用以下命令找出,我的机器就一个应用程序池,是1592,打开windbg,按f6附加进程

C:\Documents and Settings\Administrator>iisapp
W3WP.exe PID: 1592   AppPoolId: ASP.NET V2.0

然后按顺序来排查
1、加载SOS
.loadby sos mscorwks
2、找出空引用异常的方法表地址
!name2ee *!System.NullReferenceException
0:026> !name2ee *!System.NullReferenceException
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y <symbol_path> argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*********************************************************************
PDB symbol for mscorwks.dll not loaded
Module: 106f1000 (System.WorkflowServices.dll)
--------------------------------------
Module: 65ce1000 (System.Web.Services.dll)
--------------------------------------
Module: 027f1000 (SMDiagnostics.dll)
--------------------------------------
Module: 10ec1000 (System.Runtime.Serialization.dll)
--------------------------------------
Module: 64891000 (System.Configuration.dll)
--------------------------------------
Module: 65f21000 (System.Web.dll)
--------------------------------------
Module: 7a441000 (System.dll)
--------------------------------------
Module: 021e2698 (CppCodeProvider.dll)
--------------------------------------
Module: 02921000 (System.EnterpriseServices.dll)
--------------------------------------
Module: 10a11000 (System.EnterpriseServices.Wrapper.dll)
--------------------------------------
Module: 790c1000 (mscorlib.dll)
Token: 0x020000dc
MethodTable: 7931fec0
EEClass: 7914e0d0
Name: System.NullReferenceException
--------------------------------------
Module: 021e2354 (sortkey.nlp)
--------------------------------------
Module: 021e2010 (sorttbls.nlp)
--------------------------------------
Module: 021e2c04 (prcp.nlp)
--------------------------------------
Module: 695a1000 (System.Web.Mobile.dll)
--------------------------------------
Module: 021e329c (mscorlib.resources.dll)
--------------------------------------
Module: 637a1000 (System.Xml.dll)
--------------------------------------
Module: 0ea31000 (System.ServiceModel.dll)
--------------------------------------
Module: 65151000 (System.Data.dll)
--------------------------------------
Module: 5e621000 (Microsoft.JScript.dll)
--------------------------------------
Module: 021e35f0 (System.Web.resources.dll)
--------------------------------------
Module: 6c3b1000 (VJSharpCodeProvider.dll)
--------------------------------------
Module: 7ade1000 (System.Drawing.dll)
--------------------------------------
Module: 66f01000 (System.Web.RegularExpressions.dll)
--------------------------------------
Module: 100c1000 (System.ServiceModel.Web.dll)
--------------------------------------
Module: 10ba1000 (System.IdentityModel.dll)
--------------------------------------
Module: 021e2f48 (System.resources.dll)
--------------------------------------
Module: 02638280 ()
--------------------------------------
Module: 026393b4 ()
--------------------------------------
Module: 02639734 ()
--------------------------------------
Module: 10d10010 ()
--------------------------------------
Module: 026c82d4 (WebApplication1.DLL)
--------------------------------------
Module: 026c9180 ()
--------------------------------------
Module: 026c9500 ()
--------------------------------------
Module: 026c9b3c (App_Web_qt-srzwh.dll)
3、找出空引用方法表的方法描述
!dumpmt -md 7931fec0
0:026> !dumpmt -md 7931fec0
EEClass: 7914e0d0
Module: 790c1000
Name: System.NullReferenceException
mdToken: 020000dc  (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
BaseSize: 0x48
ComponentSize: 0x0
Number of IFaces in IFaceMap: 2
Slots in VTable: 21
--------------------------------------
MethodDesc Table
   Entry MethodDesc      JIT Name
79240bc8   79106234   PreJIT System.Exception.ToString()
79286a90   7910493c   PreJIT System.Object.Equals(System.Object)
79286b00   7910496c   PreJIT System.Object.GetHashCode()
792f72f0   79104990   PreJIT System.Object.Finalize()
79240bd8   7910617c   PreJIT System.Exception.get_Message()
792993f0   7910618c   PreJIT System.Exception.get_Data()
79744d94   791061c0   PreJIT System.Exception.GetBaseException()
792995d0   791061c8   PreJIT System.Exception.get_InnerException()
79745530   791061ec   PreJIT System.Exception.get_TargetSite()
792994f0   79106200   PreJIT System.Exception.get_StackTrace()
79745460   79106214   PreJIT System.Exception.get_HelpLink()
79745440   7910621c   PreJIT System.Exception.set_HelpLink(System.String)
797453a4   79106224   PreJIT System.Exception.get_Source()
79745390   7910622c   PreJIT System.Exception.set_Source(System.String)
79255968   79106264   PreJIT System.Exception.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)
79744b44   791062b4   PreJIT System.Exception.InternalToString()
79744b30   791062bc   PreJIT System.Exception.GetType()
79253fc0   7919b748   PreJIT System.NullReferenceException..ctor()
797d15ec   7919b758   PreJIT System.NullReferenceException..ctor(System.String)
797d15c4   7919b764   PreJIT System.NullReferenceException..ctor(System.String, System.Exception)
797d1610   7919b770   PreJIT System.NullReferenceException..ctor(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)
4、在空引用异常对象的构造函数上设置断点
!bpmd -md 7919b748
0:026> !bpmd -md 7919b748
MethodDesc = 7919b748
Setting breakpoint: bp 797D158C [System.NullReferenceException..ctor()]
*** WARNING: Unable to verify checksum for C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\mscorlib\9adb89fa22fd5b4ce433b5aca7fb1b07\mscorlib.ni.dll
*** ERROR: Module load completed but symbols could not be loaded for C:\WINDOWS\assembly\NativeImages_v2.0.50727_32\mscorlib\9adb89fa22fd5b4ce433b5aca7fb1b07\mscorlib.ni.dll
5、继续执行程序并测试程序
0:026> g
(638.bc8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=02b920c4 ecx=00000000 edx=00000000 esi=06b23cec edi=02b920c4
eip=1166064f esp=1138f260 ebp=1138f2cc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
WebApplication1!WebApplication1.TestException.Page_Load(System.Object, System.EventArgs)+0x8f:
1166064f 3909            cmp     dword ptr [ecx],ecx  ds:0023:00000000=????????
*** WARNING: Unable to verify checksum for C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\webapplication1\c72f0972\f7fe4744\assembly\dl3\ab709657\703b76b7_0218c901\WebApplication1.DLL

6、查看调用栈及调用栈的参数和临时变量
0:022> !clratack -a
No export clratack found
0:022> !clrstack -a
OS Thread Id: 0xbc8 (22)
ESP       EIP    
1138f260 1166064f WebApplication1.TestException.Page_Load(System.Object, System.EventArgs)
    PARAMETERS:
        this = 0x06b235c4
        sender = 0x06b235c4
        e = 0x02b920c4
    LOCALS:
        0x1138f2a0 = 0x06b243d4
        0x1138f29c = 0x00000000
        0x1138f298 = 0x00000000

1138f2d8 66f2a7ff System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr, System.Object, System.Object, System.EventArgs)
    PARAMETERS:
        fp = <no data>
        o = <no data>
        t = <no data>
        e = <no data>

1138f2e8 660b2344 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(System.Object, System.EventArgs)
    PARAMETERS:
        this = <no data>
        sender = <no data>
        e = <no data>

1138f2fc 660ab864 System.Web.UI.Control.OnLoad(System.EventArgs)
    PARAMETERS:
        this = <no data>
        e = <no data>
    LOCALS:
        <no data>

1138f310 660ab8a3 System.Web.UI.Control.LoadRecursive()
    PARAMETERS:
        this = 0x06b235c4
    LOCALS:
        <no data>
        <no data>
        <no data>

1138f328 660a7954 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)
    PARAMETERS:
        this = 0x06b235c4
        includeStagesBeforeAsyncPoint = 0x00000001
        includeStagesAfterAsyncPoint = 0x00000001
    LOCALS:
        0x1138f334 = 0x06b21d04
        0x1138f330 = 0x00000000
        0x1138f32c = 0x02a301d0
        <no data>
        <no data>
        <no data>
        <no data>
        <no data>

1138f480 660a7584 System.Web.UI.Page.ProcessRequest(Boolean, Boolean)
    PARAMETERS:
        this = 0x06b235c4
        includeStagesBeforeAsyncPoint = <no data>
        includeStagesAfterAsyncPoint = 0x00000001
    LOCALS:
        0x1138f484 = 0x00000000

1138f4b8 660a74b1 System.Web.UI.Page.ProcessRequest()
    PARAMETERS:
        this = 0x06b235c4
    LOCALS:
        0x1138f4c0 = 0x02a9e97c
        0x1138f4bc = 0x06a87bcc
        0x1138f4b8 = 0x06a87bcc

1138f4f0 660a7446 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext)
    PARAMETERS:
        this = <no data>
        context = <no data>

1138f4fc 660a7422 System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)
    PARAMETERS:
        this = <no data>
        context = <no data>

1138f510 1166025e ASP.testexception_aspx.ProcessRequest(System.Web.HttpContext)
    PARAMETERS:
        this = 0x06b235c4
        context = 0x06b21d04

1138f520 660ad8f6 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
    PARAMETERS:
        this = <no data>
    LOCALS:
        0x1138f528 = 0x06b21d04
        <no data>
        <no data>
        <no data>
        <no data>
        <no data>

1138f554 6608132c System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
    PARAMETERS:
        this = 0x02b79ab0
        step = 0x02b8fb6c
        completedSynchronously = 0x1138f5b0
    LOCALS:
        0x1138f55c = 0x00000000
        <no data>
        <no data>
        <no data>
        <no data>

1138f594 6608c3a3 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception)
    PARAMETERS:
        this = 0x02b8c614
        error = <no data>
    LOCALS:
        0x1138f5b4 = 0x00000000
        0x1138f5b0 = 0x00000001
        0x1138f5a4 = 0x02b79ab0
        0x1138f5a0 = 0x06b21d04
        0x1138f59c = 0x06b22034
        0x1138f598 = 0x06b22014
        <no data>
        0x1138f594 = 0x02b79ab0

1138f5e4 660808ac System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object)
    PARAMETERS:
        this = <no data>
        context = <no data>
        cb = <no data>
        extraData = <no data>
    LOCALS:
        <no data>

1138f600 66083e1c System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest)
    PARAMETERS:
        this = 0x02aa1354
        wr = 0x06b21418
    LOCALS:
        0x1138f600 = 0x06b21d04
        <no data>
        <no data>
        <no data>
        <no data>

1138f634 66083ac3 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest)
    PARAMETERS:
        wr = <no data>
    LOCALS:
        <no data>

1138f644 66082c5c System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32)
    PARAMETERS:
        this = 0x02b5e0e4
        ecb = <no data>
        iWRType = <no data>
    LOCALS:
        0x1138f688 = 0x01fe3d08
        0x1138f67c = 0x06b21418
        <no data>
        <no data>
        <no data>
        <no data>
        <no data>
        <no data>

1138f858 79f68c4e [ContextTransitionFrame: 1138f858]
1138f88c 79f68c4e [GCFrame: 1138f88c]
1138f9e8 79f68c4e [ComMethodFrame: 1138f9e8]
6、分析调用栈的参数和临时变量,从上面看到TestException.Page_Load有3个临时变量,其中后两个是空引用,虽然看不到这三个临时变量的变量名(不可能能看到),但根据代码可以推断出后面两个参数其中之一是handleResult的返回值,所以问题就在这儿。我们可以打印出第一个参数来看这个参数是不是我们所期望的,结果打印出来的值是个奇数,问题就确认了,到时候再来看客户为什么输入奇数就行了。
0:022> !do 0x06b243d4
Name: System.String
MethodTable: 793308ec
EEClass: 790ed64c
Size: 20(0x14) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: 1
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332b38  4000096        4         System.Int32  1 instance        2 m_arrayLength
79332b38  4000097        8         System.Int32  1 instance        1 m_stringLength
793315cc  4000098        c          System.Char  1 instance       31 m_firstChar
793308ec  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  000ce120:02a301d0 000fc948:02a301d0 0017ac48:02a301d0 <<
7933151c  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  000ce120:02a30728 000fc948:06a30bd4 0017ac48:06a87b80 <<
7、保存转储文件
.dump /f /o c:\temp.dmp

后续:如果只为了捕获异常,可以设置windbg的配置文件来让出现某些异常的时候自动调试,还可以用gflag或者手工修改注册表让某个应用崩溃的时候自动抓取Dump,本文是另一种思路,用设置断点的方式来排查问题。

关于windbg的使用,可以参考如下链接

【蛙蛙推荐】windbg使用小总结

或者熊力的《windows用户态程序高效排错》

原文地址:https://www.cnblogs.com/onlytiancai/p/1292067.html