一、环境配置
C:\MyLocalSymbols;SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols; http://10.33.40.55/symbols
上面的MyLocalSymbols目录放了系统符号表,网络地址是在本地找不到系统符号表的情况,从网络下载,最后面的是应用程序符号表
第一次使用的时候,会从网络上面下载符号表到MyLocalSymbols。(如果该目录下有其他版本的系统库的话,可以删掉之前的,或者创建一个新目录)
20180724在测试机中使用成功的symbol path是
SRV*D:\system_symbol*http://msdl.microsoft.com/download/symbols;D:\SS_MTS
二、日志文件的使用
第一步, 开启日志记录:
.logopen d:\output.txt
第二步, 运行你想要输出到文本文件中的命令:
!address
第三步, 关闭日志记录:
.logclose
第四步, 检查是否还有日志记录打开:
.logfile
三、常用的命令
1、lm:列出所有模块
2、lm v m ntdll* / lm v m * //查看模块的版本信息
3、!heap -s // 列出所有堆的统计信息
4、!heap -a [address] // 列出此堆分配的所有内存
5、dc [address] //转存出内存数据的字符
6、dps [address] //查找 一段地址内的 symbol
7、s -d 00000000 L?ffffffff [address] //查找某个值在内存空间内被谁引用过
8、dd [address] //打印出地址内的值
9、!address 打印内存信息(有用)
10、!heap -stat -h 03230000 查看线程 堆占用信息
11、!analyze -v :用于分析挂掉线程的详细情形,错误原因。(linux的当前线程的bt命令)
12、!locks :列出全部资源使用情况。
13、!locks -v 0x???????? :特定地址的死锁分析。
14、.thread 0x????????:转到某个线程堆栈,然后在执行kv就可以看到某一个线程的堆栈信息
15、!locks显示当前线程所有死锁
16、kv、kn、kb三个命令都是显示当前的线程堆栈类似于linux的gdb的bt命令
17、~*kv显示所有的线程堆栈(类似于linux的thread apply all bt)
18、.frame切换到指定的帧,类似于gdb的f命令,.frame 3进入序列号为3的帧(等同于linux的fream 4(缩写f 4))
19、dv打印局部变量类似于gdb的info locals
20、dt可以打印复杂类型变量,dt this打印类信息
21、!stl 变量名或者dt -b 变量名,可以打印stl变量
22、根据地址打印变量
dt 0x00000001`61b9ec10 CStreamDecodeAnalyze*
dt 0x00000001`61b9ec10 CStreamDecodeAnalyze(可能执行下面的命令)
类似于gdb的p *(Dahua::StreamMedia::CRtpDataSrc*)0xf5638c70
23、local变量的详细信息可以通过菜单栏的view -> local查看
四、扩展命令
1、!threads显示所有的线程
2、~50s显示50号线程(等同于linux的thread id)
3、~*e!clrstack查看所有的线程的堆栈信息,实际上使用~*kv效果是一样的
4、!clrstack 在执行完命令2之后,接着执行这个命令 会输出对应线程的完整的堆栈
所有的扩展命令都是以!开头的,但是 以!开头不一定是扩展命令,和kv、kn、kb一样
调试过程中有两种类型的扩展dll,一种是.net2,一种是.net4版本,C:\Windows\Microsoft.NET\Framework\查看该目录下最大的文件夹就是当前电脑所以支持的版本
加载可以使用.load和.loadby两种命令
使用.load命令加上扩展模块的名称或者完整的路径来加载他,如果没有指定路径,那么windbg会在扩展模块的搜索路径(EXTPATH)中寻找这个文件
使用.loadby命令加上扩展模块的名称和一个已经加载的程序模块的名称,这时windbg会在指定的程序的模块文件所在目录中寻找和加载扩展命令模块。
举例说明,.loadby sos mscorwks,会让windbg在mscorwks模块所在目录下寻找加载sos扩展模块,这样可以保证加载正确版本的sos模块
1、.loadby
4.0版本的话,加载命令如下:
.loadby sos clr
2.0版本的话,加载命令:
.loadby sos mscorwks
2、.load
.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll
.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
加载完成之后需要.reload下库,由于上面从没有加载成功过,所以下面的是否要reload不确定,网上找来的
五、使用过程中遇到的问题
1、在第一步配置好环境之后,然后lm之后发现只有ntdll库加载了符号表,其他的都没有,其实这个应该是没有问题的,执行~*kv之后应用程序的符号表会加载,然后再次执行lm既可以发现符号表都被加载了
2、dump生成之后,进行!analyze –v 会显示对应的堆栈信息已经整体概述,其中概述中有这么一行,
STACK_COMMAND: ~119s; .ecxr ; kb
那么接下来执行这个三个命令就可以直接跳转到对应的崩溃堆栈中来了,之前之前执行~119s; kb这两个命令发现堆栈和崩溃堆栈不一致,猜测可能当前线程是崩溃之前保留的线程,所有和崩溃时的线程堆栈不一致(猜测)。
六、运行状态attach dump
使用windb*生dmp
attach process
.dump /ma C:\aaa.dmp /ma产生完整信息的dump
detach
七、参考链接
句柄泄露相关信息调试方法
http://www.cnblogs.com/daxingxing/archive/2012/06/07/2540086.html
泄露不是类的时候,处理方式
http://blog.csdn.net/huntzw/article/details/21971085
常见的命令
http://www.cppblog.com/weiym/archive/2012/06/07/177958.aspx
如何打印某一个成员变量?
八、gflag、umdh内存泄露处理
通过gflag和umdh查看内存泄露问题
gflags.exe -i D:\test\590-0626\bin\mgc.exe +ust
umdh.exe -pn:mgc.exe -f:mgcl.log
umdh.exe -pn:mgc.exe -f:mgc2.log
umdh.exe mgc1.log mgc2.log -f:mgc1_mgc2.log