[ASP.NET Debugging BuggyBits读书笔记] Lab02 Crash
时间:2011-01-15 来源:李志鹏
1. 打开command-line prompt转到WinDbg目录,执行 adplus –crash –pn w3wp.exe –quiet
2. 在Review.aspx页面里点击Refresh按钮,将触发w3wp.exe进程的crash
3. 打开EventViewer,查看System.evt,找到事件记录:
可见进程被终止,是因为发生了0xe0434f4d错误,而该错误是CLR错误在系统层面的统一称呼。
查看 Application.evt,找到事件记录:
可见系统接收到了System.NullReferenceException错误。
可见是Review类型的Finalize()方法抛出了NullReferenceException。
4. 用WinDbg打开2nd chance的.dmp文件。
5. 执行 .loadby sos.dll mscorwks,执行 !pe 查看错误。执行 !dso 查看与该thread相关的所有object。
可以发现,在所有抛出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.