SOS这个工具很强大,能帮助我们分析和查询到很多有用的信息。如果配合它的扩展,还能帮我们定位一些死锁问题。
拿我上一篇谈谈.NET中常见的内存泄露问题——GC、委托事件和弱引用的代码做例子,我们可以分析一个对象到底有没有被根引用,内存地址是什么,占用了多少内存等。
SOS可以在Windbg中加载使用,也可以在Visual Studio中加载使用,为了能更方便的演示,我就说说如何在Visual Studio中加载使用
一、要启用SOS,首先要修改项目的属性,如下图
二、打开的“即时窗口”中输入“!load sos.dll”来加载SOS.dll
在“即时窗口”中输入“!help”可以获得调试命令列表(如下),输入"!help <command>" 可以获得该命令的详细信息.(运行这条命令之前一定要先加载sos,因为这个是sos的命令,感叹号不可以省略)
在debug运行时需要设置断点.load命令才能使用
一步步进行调试实战
在这段方法中,我们要证实的是,把委托赋给我们自定的事件以后,root并没有增加。
private void Register() { mybutton.Click += root.TestRoot; mybutton.Click += mybutton_Click; //我们把断点下在这一行 mybutton.Click += new Test().TestNoRoot; }
首先输入的是 !clrstack -a 命令,因为sos无法直接通过变量名来获取对象信息,因此先要找到对象的地址。可以看到在方法内没有任何的局部变量,只有一个this,在堆上的地址为0x01b46c34
我们把这个对象dump出来,用命令 !do 0x01b46c34,查找到我们需要的信息。
接着我们用命令 !gcroot 01b46e44 ,可以发现这个root对象只有一个root引用,证明了我们的弱引用并没有增加root
我们还可以通过把root变量设为null使得root对象没有引用
这里主要介绍了几个比较有用的命令,其他的命令可以通过!help来查询。