原文来自:http://blogs.msdn.com/b/tess/archive/2008/02/11/net-debugging-demos-lab-2-crash-review.aspx ui
1. 打开command-line prompt转到WinDbg目录,执行 adplus –crash –pn w3wp.exe –quiet this
2. 在Review.aspx页面里点击Refresh按钮,将触发w3wp.exe进程的crash debug
3. 打开EventViewer,查看System.evt,找到事件记录: 指针
可见进程被终止,是由于发生了0xe0434f4d错误,而该错误是CLR错误在系统层面的统一称呼。 对象
查看 Application.evt,找到事件记录: blog
可见系统接收到了System.NullReferenceException错误。 进程
可见是Review类型的Finalize()方法抛出了NullReferenceException。 事件
4. 用WinDbg打开2nd chance的.dmp文件。 get
5. 执行 .loadby sos.dll mscorwks,执行 !pe 查看错误。执行 !dso 查看与该thread相关的全部object。 string
能够发现,在全部抛出NullReferenceException的对象里,只有一个object的地址为026f4d1c,所以怀疑它才是真正抛出错误的对象。
6. 执行 !pe 026f4d1c ,获得结果以下:
能够看到与该exception相关联的方法是Review类型的Finalize()方法。
7. 能够发现该Fucntion所处的IP(Instruction pointer)是063B0f54,执行 !u 063B0F54:
能够发现063B0f54的位置介于063b0f53和063bf55之间,这里正好是执行063b0f53指令的地方,尝试把指针[ecx]的内容赋值给eax,而ecx的内容等于esi+4所指向的对象的内容。结合NullReferenceException,能够得知,esi+4指向的内容为空,因此该空值赋值给ecx之后,这是程序所访问的地址空间就变成了[0],出现NullReferenceException。
8. 在托管程序中,esi指针一般是this指针,也就是说,这个指针指向的是Review类型的的一个对象,所以咱们尝试去查看这个对象究竟包含哪些内容。执行 !do 026c15d8,获得该Review对象的内容:
可见,该对象偏置4之后(offset+4),是quote变量的值,其value值(该值指向了quote的内容的存放地点)被指为null,所以其地址值变为了00000000,若是尝试去访问0000000地址的值(命令为move ecx, dword ptr [esi+4]),就会抛出NullReferenceException
9. 查看源代码:
可见程序在对象不使用以后都会执行一个ClearReview()方法。
该方法的实际内容是将对象置位null(指针将变为0)。
对于托管对象而言,并不须要在使用以后进行析构,但是程序仍然进行了析构,其代码为:
这里程序将先进行ToString()而后再和string.empty进行比较,这里因为quote已经为空,因此执行ToString()的时候就会出现NullReferenceException.