Advanced .Net Debugging 1:你必须知道的调试工具
一、简介
我曾看到过许多开发人员使用错误的工具来分析问题,更有甚者,有些人连任何工具都没有使用。他们采取的分析方法通常包括:输出更多的调试信息,或者做一些临时性的代码审查。这里的临时性是指,通过猜测来推断问题可能来之哪个部分的代码。有时候,开发人员会幸运的发现问题刚好处于他们正在审查的代码当中。然而,在更多情况下并非如此,问题发生的位置和表现出来的位置往往相差甚远。说起来有点可笑,我很长一段时间都是这样调试的。自从我接触了《Net 高级调试》,调试原来不是这样的。通过使用一些功能强大的调试工具,开发人员可以极大的减少在分析问题时耗费的时间。
所以,我们必须学会如何使用工具进行调试,要知道每种工具在哪些情况下使用以及如何使用。这是对大家的建议,更多是对我自己的鞭策。今天我们就介绍一些调试中经常要用到的一些工具。
在开始之前,我还得说明一下,《Net 高级调试》这本书,写的挺早的,中文翻译的版本是2011年机械工业出版社出版的,里面的内容有些也比较老旧,我都做了实时的更新,都是最新的。因为这次只是工具介绍,具体的环境就不做说明了。还有,有些工具,比如:NTSD、KD等类似的命令行调试器我就不太在行了,所以我会使用在这个系列出现的GUI调试工具(Windbg)来调试问题,具体其他调试器使用方法,大家可以自行补充。
二、常用调试工具
我们想要成为高级程序员,高级的调试技巧必须掌握,当然,这些技巧需要借助工具来体现,我们下面就来介绍一下将在我这个系列里面用到的一些调试工具,当前不是全部,我会在以后得章节里,有需要在介绍一些用到的调试工具。
说起调试工具,其实有很多,他们的用途也不一样,有一部分工具侧重分析某一类特定的问题,而有些工具可以同时处理若干类问题,我们要知道每种工具在什么情况下使用以及如何使用,这一点非常重要。
1、Windows 调试工具集
Windows 调试工具集是一个免费的软件包,它有两个版本:32位和64位。在这个工具集中有3种用户态调试工具:
NTSD(Microsoft NT 符号调试器)、CDB(Microsoft 控制台调试器)
和 WinDbg,以及
一种内核态调试器 KD
。我说一下区别:NTSD 和 CDB(KD 它属于内核态调试器,但是它是命令行调试器)都是命令行调试器,Windbug 是一个具有界面的调试器,它可以更容易调试源代码。他们虽然有这些区别,但是他们使用了相同的内核调试器引擎。
【应用场合】一组调试器和调试工具。
【下载地址】
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/debugger-download-tools
【软件版本】Microsoft (R) Windows Debugger Version 10.0.22621.2428(书上:6.8.4.0)
Windebug效果如图:
NTSD如图:
我们安装了调试器工具集,也要配置环境变量,就不用每次使用都切换目录。
可以将 Windows 调试工具作为开发工具包的一部分或独立工具集获取:
a、作为 WDK 的一部分
Windows 调试工具包含在 Windows 驱动程序工具包 (WDK) 中。 若要获取 WDK,
请参阅下载 Windows 驱动程序工具包 (WDK)
。
b、作为 Windows SDK 的一部分
Windows 调试工具包含在 Windows 软件开发工具包 (SDK) 中。 若要下载安装程序或 ISO 映像,请参阅 Windows 开发人员中心上的
Windows SDK。
c、作为独立工具集
你可以单独安装适用于 Windows 的调试工具,而无需 Windows SDK 或 WDK,方法是开始安装 Windows SDK,然后在功能列表中选择“ Windows 调试工具” 以安装 (并清除) 选择所有其他功能。 若要下载安装程序或 ISO 映像,请参阅 Windows 开发人员中心上的
Windows SDK
。
我使用的Windows SDK 版本的安装,Windows SDK (10.0.22621) for Windows 11,版本 22H2 (2023 年 10 月更新) 提供了用于生成 Windows 应用程序的最新标头、库、元数据和工具。 使用此 SDK 为Windows 11版本 22H2 和早期 Windows 版本生成通用 Windows 平台 (UWP) 和 Win32 应用程序。
Windows SDK 官网下载地址:
https://developer.microsoft.com/zh-cn/windows/downloads/windows-sdk/
2、Net 8.0 可再发行组件和 Net 8.0 SDK
刚开始说起【可再发行组件】,我是一头懵,不知道是什么。知道了是什么东西,也很容易,只是我们不这样说,叫它“可再发行组件”。【Net 8.0 可再发行组件】就是 Net 8.0 Runtime 运行时的组件。
【应用场合】Net 运行时(.Net Runtime)
【下载地址】
https://dotnet.microsoft.com/zh-cn/download/dotnet/8.0
【组件版本】8.0(书上是:2.0)
点击下载地址,我们就可以进入下载页面,当然,随着时间的推移,这个版本也是会发生变化的。这个页面左侧是 Net 8.0 SDK ,右侧页面就是各种的 Runtime,有我们经常用于运行 Web 页面:ASP.NET Core 运行时 8.0.0,运行桌面程序的:NET 桌面运行时 8.0.0,等等很多。
运行时和SDK 的区别就是,【运行时】就是一个Net 运行基础的、必须的环境,很干净,包括所有的框架程序集以及 Net 运行时的二进制文件,一点多余的东西都没有。
SDK 是包含【运行时】的全部功能,只有SDK 才能使开发人员编写新的 Net 应用程序,因为它提供了所有必要的工具(编译器、汇编器、构建工具)及其库等。Net SDK 并不提供基于图形界面的集成开发环境,而只是提供了一个基于命令行的环境。我们一般选择在服务器上安装更干净的【运行时】,在开发平台选择安装 SDK。
效果如图:
3、SOS
SOS名称的来历:SOS 不是求救的意思,当 Net 框架哈仔 1.0 阶段时,Microsoft 团队使用了一个叫【STRIKE】的调试器扩展来分析 Net 代码中的各种复杂问题。当 Net 框架日趋成熟时,这个调试器扩展的名称也就逐渐演变成了“Son of Strike”(SOS)。
用于调试 Net 应用程序的扩展组件。SOS 是一个调试器扩展,用于调试 Net 应用程序,它提供了一组非常丰富的命令,这些命令使开发人员可以对 CLR进行深入分析,并且有助于找出应用程序中各种复杂错误的原因。当然,它还有一些命令可以用来查看【终结队列】、【托管堆】、【托管线程】,在托管代码中设置断点以及查看异常等。
由于SOS 能够提供 CLR 内部工作机制的抽象视图,因此在使用SOS济宁调试时,必须使用正确版本的SOS。每个版本的 Net 在发布时都带有相应的SOS,可以在以下位置找到:
%windir%\Microsoft.NET\<architecture>\<version>\sos.dll
architecture:可以是 Framework(32位)或者 Framework(64位),而 version 可以表示所使用的 Net 框架的版本。
C:\Windows\Microsoft.NET\Framework\v4.0.30319\
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\
32位 SOS 效果如图:
64位 SOS 效果如图:
Windbg Preview 是不用单独执行加载的工作的,它会自动加载它所需要的版本,如果是老版本的 Windbg,比如:windbg10 ,可以通过 .load 命令加载 SOS.dll。一般情况,使用windbg自带的命令【.load sos】即可自动加载,使用【.chain】查看加载是否成功。
我们执行【.chain】命令,看一下执行效果,说明一下,要想执行这个命令,我们要创建一个项目,通过 Windbg 加载我们的 EXE 项目,通过【g】命令运行程序,就可以执行命令了,否则看不到 SOS。效果如图:
4、SOSEX
我们在上面说了SOS.DLL,这里我们在说说 SOSEX.DLL,它也是用于调试 Net 应用程序的扩展组件,可以用于非托管代码和托管代码的调试,他是有 Steve Johnson 开发的,SOSEX表示SOS Extended。SOSEX 增加了一组功能强大的调试命令,这些命令包含【死锁检测】、基于代的垃圾收集命令以及其他一些功能强大的断点命令。
SOSEX的安装包只是一个ZIP文件,只需将 ZIP文件中压缩的文件释放到指定为止即可完成安装。
但是需要说明一下,它虽然很强大,但是只能在 Net Framework 平台上使用,我们最新的跨平台是不能使用的。太可惜了。
如果大家需要调试 Net Framework 版本的程序,它还是很有用的,大家可以去网上自行下载。
我的下载地址:
https://www.xiazaila.com/soft/46338.html
我先给大家一个印象吧,有一个直观的感觉,截图如下:
5、CLR分析器
CLR 分析器:堆内存分配情况进行分析。在调试 Net 应用程序中与内存相关的问题时,CLR分析器是一种非常有用的工具。它可以提供的功能:堆的统计信息、垃圾收集操作的统计信息、垃圾收集器句柄统计信息、垃圾收集中每代对象的总体大小、性能分析的统计信息。
CLR分析器的安装过程很简单,安装包是一个 ZIP文件,只需将 ZIP 文件的内容释放到指定的文件夹即可完成安装。它也是分为两个版本:32位的和64位的,要启动 CLR 分析器,只需运行 CLRProfiler.exe,效果如图:
运行效果如图:
官网下载地址:
https://github.com/microsoftarchive/clrprofiler/releases
6、性能计数器
在安装 Net 框架的同时会安装一组性能计数器,我们可以通过 Windows 性能监视器(Windows Performance Monitor)来查看这些性能计数器。这些性能计数器包含:
异常(.NET CLR Exceptions):与 Net 应用程序中抛出的异常相关的性能计数器。
互用性(NET CLR Interop):与 Net 应用程序中对 COM,COM+以及外部库等使用情况相关的性能计数器。
即时编译(NET CLR Jit):与 即时编译【JIT】相关的性能计数器。
加载器(NET CLR Loading):与加载 Net 各种实体【例如程序集,类型等】相关的性能计数器。
锁和线程(NET CLR LocksAndThreads):与线程以及锁定行为相关的性能计数器。
内存(NET CLR Memory):与垃圾收集器和内存使用相关的性能计数器。
网络(NET CLR Networking/NET CLR Networking 4.0.0.0):与 Net 应用程序在网络上的发送和接受等操作相关的性能计数器。
远程行为(NET CLR Remoting):与 Net 应用程序中的远程对象相关的性能计数器。
安全(NET CLR Security):与 Net 框架执行的安全检查相关的性能计数器。
我们可以在开始菜单里面找到他们,依次【Windows 管理工具】---》【性能监视器】,效果如图:
我们打开【性能监视器】,操作界面如下:
我们可以点击绿色的加号,就能看到性能计数器的类别,如图:
7、Net 反编译器
如果我们想查看已经编译后文件的源代码,怎么办呢?立刻我们就会想到反编译工具,这种编译器可以从 MSIL中生成各种高级语言代码。这种工具不少,比如以前用的比较多的 Reflector.exe,但是,相对于现在来说还是使用感觉比较差。我在这里推荐 ILSpy和 DnSpy,他们两个都可以查看元数据、IL代码,不同点就是 DnSpy 可以像 Visual Studio 那样编辑和调试代码,功能很强大。
【应用场合】ILSpy 可以反编译源码,DnSpy 可以反编译源码和调试源码。
【下载地址】ILSpy官网下载地址:
https://github.com/icsharpcode/ILSpy
DnSpy官网下载地址:
https://github.com/dnSpy/dnSpy
【软件版本】ILSpy 版本:7.2.1.6856,DnSpy 版本:
6.1.8.0
ILSpy 操作界面截图如下:
DnSpy操作界面截图如下:
8、PowerDbg
PowerDbg 是由 Roberto Farah 开发的一个库,它使开发人员通过 Powershell 来控制非托管调试器。当希望通过命令行来控制调试器的运行时,它是一个非常有用的工具,易于扩展,并且能够对常用的命令进行调用和格式化。
PowerDbg的工作原理是向运行中的 WinDbg 发送各种命令,任何命令在执行时,将首先打开一个日志文件,接下来在执行命令,最后关闭日志文件。PowerDbg 脚本通过这个日志文件来分析结果和产生输出信息。
我个人不太推荐,使用繁琐,全部是命令行,不是所见即所得的,不方便实用,还是不如直接使用 Windbg 来的更快,如果大家想试试的,也是个好事。
官网下载地址:
https://www.softpedia.com/get/Programming/Components-Libraries/PowerDbg.shtml
9、托管调试助手
托管调试助手(MDA)用于一般性的 CLR 调试,它并不是一个独立的工具,而是 CLR 中的一个组件,在运行和调试 Net 应用程序是将提供各种有用的信息。通过对【运行时】加你选哪个监测,可以找出一些常见的编程错误并且能在发布应用程序之前修复它们。MDA 可以分为几类:
非托管互用性:与非托管互用性问题相关的调试助手。
非托管互用性(COM):与 COM 非托管互操作问题相关的调试助手。
非托管互用性(P/Invoke):与平台调用非托管互用性问题相关的调试助手。
加载器:CLR 加载器相关的调试助手。
线程:与线程问题相关的调试助手。
BCL:与基础类库问题相关的调试助手。
其他:其他调试问题。
如果大家想了解 MDA 更多的内容,可以直接去微软的网站上去查看。以下是网址:
https://learn.microsoft.com/zh-cn/dotnet/framework/debug-trace-profile/diagnosing-errors-with-managed-debugging-assistants
。这里面说的很清楚,直接学习就可以了。
三、总结
新的开始,新的征程。我从今天开始要写一个新的系列,这个系列完全是按着《Advanced .Net Debugging》这本书的节奏和章节来的,当然了,有的内容过于老旧还是会有所删减,但是质量不会降低。我写完上一个高级调试的系列,收货还是挺丰富的。那个系列可以带我入门,如果想真的有所提升,还是需要将整本书重新研读。估计这个系列的路也不一定好走,还好我喜欢编程,喜欢知其然,也要做到知其所以然,有这样的决心支持我走下去。不忘初心,继续努力吧。