WinDbg 调试步骤总结(未完待续......)

卷儿哥 2023年11月23日 220次浏览

windbg调试系列教程:sos扩展的介绍和使用

  • 对于一个崩溃类的dump,寻找崩溃点非常重要,常用的命令就是 !analyze -v
  • 其他常规命令:
? 获取命令提示
D 查看内存信息
K 观察栈
~ 显示和控制线程 ~number s number为线程id 如:~1s为获取1号线程的上下文
Q 退出
!runaway 查看线程占用cpu时间,可看出哪个线程占用时间最高(所有线程)
.dump /ma E:/dumps/myapp.dmp 抓取dump

.help 获取命令提示
.cls 清屏
.ttime 查看线程占用cpu时间,可看出哪个线程占用时间最高(当前线程)
3..扩展命令
. chain 获取命令集列表。在已经加载的动态链接库中。
.load/.unload 加载/卸载命令模块
**!模块名.help **查看某个扩展库中包含的扩展命令

1、常规分析步骤

  • 运行.time命令会显示时间相关的信息,如系统运行时间,进程运行时间和CPU花费在内核态和用户态的时间
  • 通过!threadpool命令我们能准确知道创建dump时cpu的使用率
  • !runaway这个命令用于显示所有正在运行的线程和它们的CPU使用率
  • !threads显示当前所有的托管线程信息

线程ID为XXXX表示该线程已结束,并在等待回收。我们也能看到线程ID为22的线程正在终结(finalizer)。假如我们使用!runaway命令时看到22线程有大量的cpu活动,可能我们的程序有终结(finalizer)问题。

  • 切换到指定线程 ~[thread id]s
  • !clrstack显示当前线程的堆栈信息
  • !clrstack -p ,还能看到方法调用的参数和局部变量信息
  • !do 0x27246e38 会打印出指定地址的对象的相关信息
  • !dso 使用该命令我们可以查看到当前线程的堆栈引用的所有托管对象
  • !da 27239b98 会打印出指定地址的数组对象的相关信息
  • !objsize 27239b98 打印对象的大小
  • !dumpheap会打印出所有在托管堆中的对象信息
  • !dumpheap -stat 输出总结后的信息
  • !dumpheap -mt 14ef4718 查看指定对象类型的详细信息 (MT字段地址(14ef4718)
  • !dumpheap -type可以根据字符串来匹配对应的对象类型

如我们输入命令“!dumpheap -type System.Web”,是指显示所有类名包含有“System.Web”字符串的对象信息。 其他参数-min和-max是接受表示对象大小的最大值和最小值(单位字节),命令会只列出大于指定值或小于指定值的对象信息

WinDbg常用命令

2、内存溢出分析

C# 会抛一个 OutOfMemoryException 异常,而且还会附加到那个执行线程上,所以先用 !t 命令调出当前的所有托管线程

  • 调出当前的所有托管线程

!t 命令调出当前的所有托管线程
!pe 查查这个异常的调用栈信息

!t
!pe 57b53d90
  • 鉴别是否为非托管堆出的问题
!address -summary #线程栈空间
!eeheap -gc #查看GC堆大小
!dumpheap -stat 

查看 MEM_COMMIT Size ≈ GC Heap Size 即可
用 !address -summary 查看进程的内存使用量
其中 MEM_COMMIT 指标可以看出内存使用量
MEM_COMMIT (1.28G) = Image (228M) + Heap (69M) + Stack (18M) + GCHeap(450M) + GCLoader (153M) + else = 918M

用 !gcheap -gc 看看托管堆的大小为 1.28 G
最后一行可以看出托管堆占用了 425453488/1024/1024 = 405M

  • 查看每个线程都在做什么

用 ~*e !clrstack 调出所有线程的托管栈,检查重复最多的线程方法栈