我曾在以前写过一篇文章,介绍如何使用 adplus 的配置脚本跟踪异常。
通常,方法都写得很短,以至于只要知道哪个函数里有异常,就肯定能跟踪到原因。但是大家都明白,我们并没有生活在那个完美世界里——只需要编写模块化的应用程序,然后一切都漂漂亮亮地排好了。:)
假设你在堆中发现了这么一个异常:
0:025> !dumpobj 02b7191c <br></br>Name: System.NullReferenceException<br></br>MethodTable: 7915ec4c<br></br>EEClass: 791ea18c<br></br>Size: 72(0x48) bytes (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)<br></br>Fields: MT Field Offset Type VT Attr Value Name<br></br>790fa3e0 40000b5 4 System.String 0 instance 00000000 _className 79109208 40000b6 8 ...ection.MethodBase 0 instance 00000000 _exceptionMethod<br></br>790fa3e0 40000b7 c System.String 0 instance 00000000 _exceptionMethodString<br></br>790fa3e0 40000b8 10 System.String 0 instance 02b719bc _message 79113dfc 40000b9 14 ...tions.IDictionary 0 instance 00000000 _data<br></br>790fa9e8 40000ba 18 System.Exception 0 instance 00000000 _innerException<br></br>790fa3e0 40000bb 1c System.String 0 instance 00000000 _helpURL<br></br>790f9c18 40000bc 20 System.Object 0 instance 02b71a38 _stackTrace<br></br>790fa3e0 40000bd 24 System.String 0 instance 00000000 _stackTraceString<br></br>790fa3e0 40000be 28 System.String 0 instance 00000000 _remoteStackTraceString<br></br>790fed1c 40000bf 34 System.Int32 0 instance 0 _remoteStackIndex<br></br>790f9c18 40000c0 2c System.Object 0 instance 00000000 _dynamicMethods<br></br>790fed1c 40000c1 38 System.Int32 0 instance -2147467261 _HResult<br></br>790fa3e0 40000c2 30 System.String 0 instance 00000000 _source<br></br>790fe160 40000c3 3c System.IntPtr 0 instance 34270984 _xptrs<br></br>790fed1c 40000c4 40 System.Int32 0 instance -1073741819 _xcode 0:025> !printexception 02b7191c <p>Exception object: 02b7191c Exception type: System.NullReferenceException</p><br></br>Message: Object reference not set to an instance of an object.<br></br>InnerException: (none)<br></br>StackTrace (generated):<br></br> SP IP Function<br></br> 020AF378 029C3269 <strong>DisplayUserInfo.Page_Load(System.Object, System.EventArgs)</strong><p>StackTraceString: (none)</p><br></br>
从堆栈中我们得知,NullReference 异常发生在 DisplayUserInfo.Page_Load 函数里,但是如何确切地知道在函数的哪个地方呢?还有,你怎么得知是什么引起了异常?
我常做的第一件事,就是如果有代码就去查看代码。如果没有代码,那么我就用 sos.dll 中的 !savemodule 和 !saveallmodules(!sam)从 dump 中抽取出 dll。在 dump 被获取时,sos.dll 将给我一个加载到内存中的 dll 原样拷贝。(一个小警告,!sam 的功能在 2.0 版的 sos.dll 中并不存在,所以在 2.0 中你得使用 savemodule)
因此对于这个异常,我就知道是在 IP(指令指针)0x029C3269 处出错。然后我可以用此地址先得到这个方法的描述符(使用 !ip2md——Instruction Pointer to Method Descriptor)。
<br></br>0:025> !ip2md <strong>0x029C3269</strong><br></br>MethodDesc: 0ee335b8<p><strong>Method Name: DisplayUserInfo.Page_Load(System.Object, System.EventArgs)</strong>Class: 0297a5b8</p><br></br>MethodTable: 0ee335ec<br></br>mdToken: 06000013<br></br>Module: 0ee329c4<br></br>IsJitted: yes<br></br>m_CodeOrIL: 029c3110<br></br>
然后 dump 出方法表,找到由这段代码编译成的 dll。
0:025> !dumpmt <strong>0ee335ec</strong><br></br>EEClass: 0297a5b8<br></br>Module: 0ee329c4<br></br>Name: DisplayUserInfo<br></br><strong>mdToken: 02000004 (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\debuggersamples\e7443224\5232f845\App_Web_dmjhn1yn.dll)<br></br></strong>BaseSize: 0x180<br></br>ComponentSize: 0x0<br></br>Number of IFaces in IFaceMap: c<br></br>Slots in VTable: 130<br></br>
一旦我们知道是哪个 dll,就能通过运行 lmv m 来找到其载入地址。
0:025> <strong>lmv mApp_Web_dmjhn1yn</strong><br></br>start end module name<br></br>0f280000 0f288000 App_Web_dmjhn1yn (deferred) <br></br> Image path: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\debuggersamples\e7443224\5232f845\App_Web_dmjhn1yn.dll<br></br> Image name: App_Web_dmjhn1yn.dll<br></br> Using CLR debugging support for all symbols<br></br> Has CLR image header, track-debug-data flag not set<br></br> Timestamp: Thu May 18 13:24:36 2006 (446C5974)<br></br> CheckSum: 00000000<br></br> ImageSize: 00008000<br></br> File version: 0.0.0.0<br></br> Product version: 0.0.0.0<br></br> File flags: 0 (Mask 3F)<br></br> File OS: 4 Unknown Win32<br></br> File type: 2.0 Dll<br></br> File date: 00000000.00000000<br></br> Translations: 0000.04b0<br></br> InternalName: App_Web_dmjhn1yn.dll<br></br> OriginalFilename: App_Web_dmjhn1yn.dll<br></br> ProductVersion: 0.0.0.0<br></br> FileVersion: 0.0.0.0<br></br> FileDescription: <br></br> LegalCopyright:<br></br>
得到这个以后,我们现在就能从内存 dump 中抽取出汇编代码(App_Web_dmjhn1yn.dll):
0:025> !savemodule <strong>0f280000 </strong>f:\App_Web_dmjhn1yn.dll<br></br>3 sections in file<br></br>section 0 - VA=2000, VASize=1af4, FileAddr=200, FileSize=1c00<br></br>section 1 - VA=4000, VASize=2c8, FileAddr=1e00, FileSize=400<br></br>section 2 - VA=6000, VASize=c, FileAddr=2200, FileSize=200<br></br>
好了,现在我们就有了这个 dll,但如何得到它的实际代码呢?
嗯,可以用 ildasm.exe 打开它,找到 DisplayUserInfo.Page_Load 函数,就会看到一些相对可读的中间语言代码。
我喜欢用的工具是 Lutz Roeder 的反射器,从 http://www.aisto.com/roeder/dotnet/ 处可以得到。当我浏览到 DisplayUserInfo.Page_Load 函数的时候,这个反射器就输出了以下内容:
protected void Page_Load(object sender, EventArgs e)<br></br>{<br></br> try<br></br> {<br></br> this.LblWelcomeMsg.Text = "Welcome " + this.Session["username"];<p> if (this.Session["role"].ToString() == "Administrator")</p><br></br> {<br></br> this.btnEditRoll.Enabled = true;<br></br> }<br></br> else<br></br> {<br></br> this.btnEditRoll.Enabled = false;<br></br> }<p> TableHeaderRow row1 = new TableHeaderRow();</p><br></br> TableHeaderCell cell1 = new TableHeaderCell();<br></br> cell1.Text = "Blogs";<br></br> row1.Cells.Add(cell1);<br></br> this.tblBlogRoll.Rows.Add(row1);<br></br> ArrayList list1 = (ArrayList) this.Session["BlogRoll"];<p> for (int num1 = 0; num1 < list1.Count; num1++)</p><br></br> {<br></br> TableCell cell2 = new TableCell();<br></br> cell2.Text = list1[num1].ToString();<br></br> TableRow row2 = new TableRow();<br></br> row2.Cells.Add(cell2);<br></br> tblBlogRoll.Rows.Add(row2);<br></br> }<br></br> }<br></br> catch (Exception)<br></br> {<br></br> base.Response.Write("An exception occurred");<br></br> }<br></br>}<br></br>
很酷吧!:) 恰恰是原始代码的一个准确复制品……但是……光有代码并不能真的告诉我们到底异常出现在哪里。因此,让我们回到指令指针处,并且用 !u 反汇编 dump 中的函数,然后就能搜索距离目前指令指针最近的那条指令。来看看我们在哪儿……
0:025> !u <br></br>029c3269 Normal JIT generated code DisplayUserInfo.Page_Load(System.Object, System.EventArgs) Begin <br></br>029c3110, size 214<br></br>029c3110 55 push ebp<br></br>029c3111 8bec mov ebp,esp<br></br>029c3113 57 push edi<br></br>029c3114 56 push esi<br></br>029c3115 53 push ebx<br></br>029c3116 83ec20 sub esp,20h<br></br>029c3119 33c0 xor eax,eax<br></br>029c311b 8945e8 mov dword ptr [ebp-18h],eax<br></br>029c311e 894ddc mov dword ptr [ebp-24h],ecx<br></br>029c3121 8b45dc mov eax,dword ptr [ebp-24h]<br></br>029c3124 8945d4 mov dword ptr [ebp-2Ch],eax<br></br>029c3127 8bb86c010000 mov edi,dword ptr [eax+16Ch]<br></br>029c312d 8b354444a30a mov esi,dword ptr ds:[0AA34444h]<br></br>029c3133 8bc8 mov ecx,eax<br></br>029c3135 8b01 mov eax,dword ptr [ecx]<br></br>029c3137 ff90a8010000 call dword ptr [eax+1A8h]<br></br>029c313d 8bc8 mov ecx,eax<br></br>029c313f 8b151844a30a mov edx,dword ptr ds:[0AA34418h]<br></br>029c3145 3909 cmp dword ptr [ecx],ecx<br></br>029c3147 e8c4b7de65 call System_Web_ni!System.Web.SessionState.HttpSessionState.get_Item(System.String) (687ae910)<br></br>029c314c 8bd0 mov edx,eax<br></br>029c314e 8bce mov ecx,esi<br></br>029c3150 e863e79a76 call USERENV!ProcessGPORegistryPolicy+0xdf (769ae763) (USERENV!ProcessGPORegistryPolicy)<br></br>029c3155 8bd0 mov edx,eax<br></br>029c3157 8bcf mov ecx,edi<br></br>029c3159 8b01 mov eax,dword ptr [ecx]<br></br>029c315b ff90fc010000 call dword ptr [eax+1FCh]<br></br>029c3161 8b4dd4 mov ecx,dword ptr [ebp-2Ch]<br></br>029c3164 8b01 mov eax,dword ptr [ecx]<br></br>029c3166 ff90a8010000 call dword ptr [eax+1A8h]<br></br>029c316c 8bc8 mov ecx,eax<br></br>029c316e 8b152044a30a mov edx,dword ptr ds:[0AA34420h]<br></br>029c3174 3909 cmp dword ptr [ecx],ecx<br></br>029c3176 e895b7de65 call System_Web_ni!System.Web.SessionState.HttpSessionState.get_Item(System.String) (687ae910)<br></br>029c317b 8bc8 mov ecx,eax<br></br>029c317d 8b01 mov eax,dword ptr [ecx]<br></br>029c317f ff5028 call dword ptr [eax+28h]<br></br>029c3182 8b152444a30a mov edx,dword ptr ds:[0AA34424h]<br></br>029c3188 8bc8 mov ecx,eax<br></br>029c318a e861879876 call USERENV!MyRegLoadKeyEx+0x21a (76988761) (USERENV!MyRegLoadKeyEx)<br></br>029c318f 25ff000000 and eax,0FFh<br></br>029c3194 7418 je App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x9e (<br></br>029c31ae)<br></br>029c3196 8b45d4 mov eax,dword ptr [ebp-2Ch]<br></br>029c3199 8b8874010000 mov ecx,dword ptr [eax+174h]<br></br>029c319f ba01000000 mov edx,1<br></br>029c31a4 8b01 mov eax,dword ptr [ecx]<br></br>029c31a6 ff9098010000 call dword ptr [eax+198h]<br></br>029c31ac eb13 jmp App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0xb1 (<br></br>029c31c1)<br></br>029c31ae 8b45d4 mov eax,dword ptr [ebp-2Ch]<br></br>029c31b1 8b8874010000 mov ecx,dword ptr [eax+174h]<br></br>029c31b7 33d2 xor edx,edx<br></br>029c31b9 8b01 mov eax,dword ptr [ecx]<br></br>029c31bb ff9098010000 call dword ptr [eax+198h]<br></br>029c31c1 b9c86ca568 mov ecx,offset System_Web_ni+0x496cc8 (68a56cc8)<br></br>029c31c6 e851ee78ff call 0215201c (JitHelp: CORINFO_HELP_NEWSFAST)<br></br>029c31cb 8bf0 mov esi,eax<br></br>029c31cd 8bce mov ecx,esi<br></br>029c31cf e82448ef65 call System_Web_ni!System.Web.UI.WebControls.TableHeaderRow..ctor() (688b79f8)<br></br>029c31d4 b9a08ca668 mov ecx,offset System_Web_ni+0x4a8ca0 (68a68ca0)<br></br>029c31d9 e83eee78ff call 0215201c (JitHelp: CORINFO_HELP_NEWSFAST)<br></br>029c31de 8bf8 mov edi,eax<br></br>029c31e0 8bcf mov ecx,edi<br></br>029c31e2 e86144ef65 call System_Web_ni!System.Web.UI.WebControls.TableHeaderCell..ctor() (688b7648)<br></br>029c31e7 8b156844a30a mov edx,dword ptr ds:[0AA34468h]<br></br>029c31ed 8bcf mov ecx,edi<br></br>029c31ef 8b01 mov eax,dword ptr [ecx]<br></br>029c31f1 ff9014020000 call dword ptr [eax+214h]<br></br>029c31f7 8bce mov ecx,esi<br></br>029c31f9 8b01 mov eax,dword ptr [ecx]<br></br>029c31fb ff90f0010000 call dword ptr [eax+1F0h]<br></br>029c3201 8bc8 mov ecx,eax<br></br>029c3203 8bd7 mov edx,edi<br></br>029c3205 3909 cmp dword ptr [ecx],ecx<br></br>029c3207 e85c3fef65 call System_Web_ni!System.Web.UI.WebControls.TableCellCollection.Add(System.Web.UI.WebControls.TableCell) (688b7168)<br></br>029c320c 8b45d4 mov eax,dword ptr [ebp-2Ch]<br></br>029c320f 8b8870010000 mov ecx,dword ptr [eax+170h]<br></br>029c3215 8b01 mov eax,dword ptr [ecx]<br></br>029c3217 ff9028020000 call dword ptr [eax+228h]<br></br>029c321d 8bc8 mov ecx,eax<br></br>029c321f 8bd6 mov edx,esi<br></br>029c3221 3909 cmp dword ptr [ecx],ecx<br></br><strong>029c3223 e8a048ef65 call System_Web_ni!System.Web.UI.WebControls.TableRowCollection.Add(System.Web.UI.WebControls.TableRow) (688b7ac8)<br></br></strong>029c3228 8b4dd4 mov ecx,dword ptr [ebp-2Ch]<br></br>029c322b 8b01 mov eax,dword ptr [ecx]<br></br>029c322d ff90a8010000 call dword ptr [eax+1A8h]<br></br>029c3233 8bc8 mov ecx,eax<br></br>029c3235 8b156c44a30a mov edx,dword ptr ds:[0AA3446Ch]<br></br>029c323b 3909 cmp dword ptr [ecx],ecx<br></br><strong>029c323d e8ceb6de65 call System_Web_ni!System.Web.SessionState.HttpSessionState.get_Item(System.String) (687ae910)<br></br></strong>029c3242 8bf0 mov esi,eax<br></br>029c3244 85f6 test esi,esi<br></br>029c3246 7418 je App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x150 (<br></br>029c3260)<br></br>029c3248 813eb0361079 cmp dword ptr [esi],offset mscorlib_ni+0x436b0 (791036b0)<br></br>029c324e 7502 jne App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x142 (<br></br>029c3252)<br></br>029c3250 eb0e jmp App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x150 (<br></br>029c3260)<br></br>029c3252 8bd6 mov edx,esi<br></br>029c3254 b9b0361079 mov ecx,offset mscorlib_ni+0x436b0 (791036b0)<p><strong>029c3259 e84e895277 call mscorwks!JIT_ChkCastClassSpecial (79eebbac)</strong>029c325e 8bf0 mov esi,eax</p><br></br>029c3260 8975d8 mov dword ptr [ebp-28h],esi<br></br>029c3263 33db xor ebx,ebx<br></br>029c3265 8b4dd8 mov ecx,dword ptr [ebp-28h]<p><strong>029c3268 8b01 mov eax,dword ptr [ecx]</strong>029c326a ff5040 call dword ptr [eax+40h]</p><br></br>029c326d 85c0 test eax,eax<br></br>029c326f 0f8e87000000 jle App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x1ec (<br></br>029c32fc)<br></br>029c3275 b9cc00a568 mov ecx,offset System_Web_ni+0x4900cc (68a500cc)<br></br>029c327a e89ded78ff call 0215201c (JitHelp: CORINFO_HELP_NEWSFAST)<br></br>029c327f 8bf8 mov edi,eax<br></br>029c3281 8bcf mov ecx,edi<p><strong>029c3283 e89897e765 call System_Web_ni!System.Web.UI.WebControls.TableCell..ctor() (6883ca20)</strong>029c3288 8bd3 mov edx,ebx</p><br></br>029c328a 8b4dd8 mov ecx,dword ptr [ebp-28h]<br></br>029c328d 8b01 mov eax,dword ptr [ecx]<br></br>029c328f ff5054 call dword ptr [eax+54h]<br></br>029c3292 8bc8 mov ecx,eax<br></br>029c3294 8b01 mov eax,dword ptr [ecx]<br></br>029c3296 ff5028 call dword ptr [eax+28h]<br></br>029c3299 8bd0 mov edx,eax<br></br>029c329b 8bcf mov ecx,edi<br></br>029c329d 8b01 mov eax,dword ptr [ecx]<br></br>029c329f ff9014020000 call dword ptr [eax+214h]<br></br>029c32a5 b9843da668 mov ecx,offset System_Web_ni+0x4a3d84 (68a63d84)<br></br>029c32aa e86ded78ff call 0215201c (JitHelp: CORINFO_HELP_NEWSFAST)<br></br>029c32af 8bf0 mov esi,eax<br></br>029c32b1 8bce mov ecx,esi<br></br>029c32b3 e8b057e665 call System_Web_ni!System.Web.UI.WebControls.TableRow..ctor() (68828a68)<br></br>029c32b8 8bce mov ecx,esi<br></br>029c32ba 8b01 mov eax,dword ptr [ecx]<br></br>029c32bc ff90f0010000 call dword ptr [eax+1F0h]<br></br>029c32c2 8bc8 mov ecx,eax<br></br>029c32c4 8bd7 mov edx,edi<br></br>029c32c6 3909 cmp dword ptr [ecx],ecx<br></br>029c32c8 e89b3eef65 call System_Web_ni!System.Web.UI.WebControls.TableCellCollection.Add(System.Web.UI.WebControls.TableCell) (688b7168)<br></br>029c32cd 8b45d4 mov eax,dword ptr [ebp-2Ch]<br></br>029c32d0 8b8870010000 mov ecx,dword ptr [eax+170h]<br></br>029c32d6 8b01 mov eax,dword ptr [ecx]<br></br>029c32d8 ff9028020000 call dword ptr [eax+228h]<br></br>029c32de 8bc8 mov ecx,eax<br></br>029c32e0 8bd6 mov edx,esi<br></br>029c32e2 3909 cmp dword ptr [ecx],ecx<br></br>029c32e4 e8df47ef65 call System_Web_ni!System.Web.UI.WebControls.TableRowCollection.Add(System.Web.UI.WebControls.TableRow) (688b7ac8)<br></br>029c32e9 83c301 add ebx,1<br></br>029c32ec 8b4dd8 mov ecx,dword ptr [ebp-28h]<br></br>029c32ef 8b01 mov eax,dword ptr [ecx]<br></br>029c32f1 ff5040 call dword ptr [eax+40h]<br></br>029c32f4 3bc3 cmp eax,ebx<br></br>029c32f6 0f8f79ffffff jg App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x165 (<br></br>029c3275)<br></br>029c32fe 8b4ddc mov ecx,dword ptr [ebp-24h]<br></br>029c3301 e84a2be165 call System_Web_ni!System.Web.UI.Page.get_Response() (687d5e50)<br></br>029c3306 8bc8 mov ecx,eax<br></br>029c3308 8b155c44a30a mov edx,dword ptr ds:[0AA3445Ch]<br></br>029c330e 3909 cmp dword ptr [ecx],ecx<br></br>029c3310 e8e3b4cd65 call System_Web_ni!System.Web.HttpResponse.Write(System.String) (6869e7f8)<br></br>029c3315 e8df2f5d77 call mscorwks!JIT_EndCatch (79f962f9)<br></br>029c331a 8d65f4 lea esp,[ebp-0Ch]<br></br>029c331d 5b pop ebx<br></br>029c331e 5e pop esi<br></br>029c331f 5f pop edi<br></br>029c3320 5d pop ebp<br></br>029c3321 c20400 ret 4<br></br>
下面这行:
<strong>029c3268 8b01 mov eax,dword ptr [ecx]</strong>
……正是我们当前 IP 的前一行,这也就意味着它是引起 NullReferenceException 的代码行。
我把相邻的几行标记成灰色,以便帮助我们比较反汇编代码和反编译代码。
反汇编代码:
<strong>029c3223 e8a048ef65 call System_Web_ni!System.Web.UI.WebControls.TableRowCollection.Add(System.Web.UI.WebControls.TableRow) (688b7ac8)</strong><br></br>029c3228 8b4dd4 mov ecx,dword ptr [ebp-2Ch]<br></br>029c322b 8b01 mov eax,dword ptr [ecx]<br></br>029c322d ff90a8010000 call dword ptr [eax+1A8h]<br></br>029c3233 8bc8 mov ecx,eax<br></br>029c3235 8b156c44a30a mov edx,dword ptr ds:[0AA3446Ch]<br></br>029c323b 3909 cmp dword ptr [ecx],ecx<p><strong>029c323d e8ceb6de65 call System_Web_ni!System.Web.SessionState.HttpSessionState.get_Item(System.String) (687ae910)</strong>029c3242 8bf0 mov esi,eax</p><br></br>029c3244 85f6 test esi,esi<br></br>029c3246 7418 je App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x150 (<br></br>029c3260)<br></br>029c3248 813eb0361079 cmp dword ptr [esi],offset mscorlib_ni+0x436b0 (791036b0)<br></br>029c324e 7502 jne App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x142 (<br></br>029c3252)<br></br>029c3250 eb0e jmp App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x150 (<br></br>029c3260)<br></br>029c3252 8bd6 mov edx,esi<br></br>029c3254 b9b0361079 mov ecx,offset mscorlib_ni+0x436b0 (791036b0)<p><strong>029c3259 e84e895277 call mscorwks!JIT_ChkCastClassSpecial (79eebbac)</strong>029c325e 8bf0 mov esi,eax</p><br></br>029c3260 8975d8 mov dword ptr [ebp-28h],esi<br></br>029c3263 33db xor ebx,ebx<br></br>029c3265 8b4dd8 mov ecx,dword ptr [ebp-28h]<p><strong>029c3268 8b01 mov eax,dword ptr [ecx]</strong>029c326a ff5040 call dword ptr [eax+40h]</p><br></br>029c326d 85c0 test eax,eax<br></br>029c326f 0f8e87000000 jle App_Web_dmjhn1yn!DisplayUserInfo.Page_Load(System.Object, System.EventArgs)+0x1ec (<br></br>029c32fc)<br></br>029c3275 b9cc00a568 mov ecx,offset System_Web_ni+0x4900cc (68a500cc)<br></br>029c327a e89ded78ff call 0215201c (JitHelp: CORINFO_HELP_NEWSFAST)<br></br>029c327f 8bf8 mov edi,eax<br></br>029c3281 8bcf mov ecx,edi<br></br><strong>029c3283 e89897e765 call System_Web_ni!System.Web.UI.WebControls.TableCell..ctor() (6883ca20)</strong>
反射器得到的代码:
this.tblBlogRoll.Rows.Add(row1);ArrayList list1 = (ArrayList) this.Session["BlogRoll"];<br></br>for (int num1 = 0; num1 < list1.Count; num1++)<br></br>{<br></br> TableCell cell2 = new TableCell();<br></br> cell2.Text = list1[num1].ToString();<br></br> TableRow row2 = new TableRow();<br></br>
我们可以看到对 this.tblBlogRoll.Rows.Add(System_Web_ni!System.Web.UI.WebControls.TableRowCollection.Add) 和 this.Session“BlogRoll” 的调用,后面跟着的是 ArrayList 的类型转换(mscorwks!JIT_ChkCastClassSpecial)。
在加粗的代码行之后,我们可以看到 new TableCell(System_Web_ni!System.Web.UI.WebControls.TableCell.ctor) 的调用,这意味着那行加粗代码一定是在 for 行中的某条指令:
for (int num1 = 0; num1 < list1.Count; num1++)<br></br>
更具体地说,是 list1.Count 引起了这个空引用异常。换句话说,list1 是一个空引用,因为 this.Session[“BlogRoll”] 是空值,当试图使用它的 Count 属性时,就进行了一次空引用。所以,要避免这个问题,我们需要在把 Session[“BlogRoll”] 赋给 ArrayList 变量前,对它进行一次空引用检查。
顺带提一下,这个方法不仅仅可以应用在异常方面。你还能用它判断出具体要在哪里加锁,还有其他类似的内容,但最可能用到的地方还是异常。
下回见……
评论