一、介绍
    今天是《Net 高级调试》的第九篇文章。这篇文章设计的内容挺多的,比如:扩展的断点支持,如何查找元数据,栈回溯,对象检查,死锁检测等等,内容挺多的。功能特别强大,使用特别方便,但是需要说明一点,这些功能不是 SOS 的功能,是 SOSEX 的扩展功能,但是,这一系列功能只是支持 Net Framework,在 Net Core 跨平台版本是不支持的。虽然这些都是基础,如果这些掌握不好,以后的高级调试的道路,也不好走。当然了,第一次看视频或者看书,是很迷糊的,不知道如何操作,还是那句老话,一遍不行,那就再来一遍,还不行,那就再来一遍,俗话说的好,书读千遍,其意自现。
     如果在没有说明的情况下,所有代码的测试环境都是 Net Framewok 4.8,但是,有些项目需要使用 Net Core 的项目,我会在项目章节里进行说明。好了,废话不多说,开始我们今天的调试工作。

       调试环境我需要进行说明,以防大家不清楚,具体情况我已经罗列出来。
          操作系统:Windows Professional 10
          调试工具:Windbg Preview(可以去Microsoft Store 去下载)
          开发工具:Visual Studio 2022
          Net 版本:Net Framework 4.8
          CoreCLR源码:源码下载

二、基础知识

    1、SOSEX调试扩展
        不得不说在调试 Net Framework 程序的时候,这个扩展调试组件的使用率是仅次于官方的 SOS 插件的,这个插件的一个特点就是能看到大量的命令是以 m 开头的,对应于 非托管命令的托管命令的表示。

        这一篇文章只是介绍常用的几个命令,如果大家想了解更多,可以使用【!sosex.help】命令,查看 SOSEX 插件的所有命令。

    2、几个相当实用的扩展命令。

        2.1、!mbp 下断点命令。
            相信大家都用过 !bp 命令,这个命令是可以对非托管函数下断点,如果我们想对托管函数下断点,就可以使用 【!mbp】 这个命令,它是【bp】命令托管形式,可以给托管方法下断点。

            【!mbp】命令使用的时候要注意一点,命令后跟的是文件名,包含后缀名,如果类是独立的类文件,就写这个类文件的名称就可以,如果是多个类包含在一个类文件里,就写包含多个类文件的名称就可以。

        2.2、观察对象布局。
            一般我们使用【!do】命令观察一个对象,但是这样只能观察到一个平面图,不能查看到立体的对象,如果想更全面的了解一个对象,我们可以使用【!mdt】命令,立体对象是指:引用类型包含引用类型,具有多层,【!do】命令只能查看当前层对象的结构。

        2.3、查找托管堆中指定的字符串。
            这个在 dump 调试的过程中做托管的内存搜索很有用,使用【!strings -m:xxx】命令。

        2.4、搜索元数据。
            我们在以前的调试 Notepad 的 SaveFile 方法的时候,使用【x】命令,这里也有对应的托管版本的命令,就是【!mx】,这个命令对于我们查找函数特别拥有。
        2.5、观察 Free 块。
            这是一个比较高级的命令,在分析托管堆碎片的时侯比较有用,能够提高分析效率。我们可以使用【!mfrag】命令。

        2.6、死锁检测。
            大家都知道【死锁】相互等待对方释放锁资源造成的,一旦出现了死锁的问题,我们可以用手工的方式分析出来的,但是这样费时费力,SOSEX 提供了一个检测命令,就是【!dlk(deadlock)】命令,用来检测死锁问题。

三、调试过程
    废话不多说,这一节是具体的调试操作的过程,又可以说是眼见为实的过程,在开始之前,我还是要啰嗦两句,这一节分为两个部分,第一部分是测试的源码部分,没有代码,当然就谈不上测试了,调试必须有载体。第二部分就是根据具体的代码来证实我们学到的知识,是具体的眼见为实。

    1、测试源码
        1.1、Example_9_1_1 项目的源码
            Program 的代码:
Net 高级调试之九:SOSEX 扩展命令介绍-LMLPHPNet 高级调试之九:SOSEX 扩展命令介绍-LMLPHP
 1 namespace Example_9_1_1
 2 {
 3     internal class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             int a = 10;
 8             int b = 11;
 9             int c = 12;
10 
11             var person = new Person();
12 
13             person.Show();
14 
15             Console.ReadLine();
16         }
17     }
18 }
11-16 11:52