VC++内存泄漏检测方法(5):使用强大的Windbg工具,重点是Symbols Path设置

前面4篇文章提到的方法,已经可以解决我们的大部分内存泄露问题了,但是这些方法是有前提的,那就是一定要有源代码,而且还只能是Debug版本调试模式下。实际上很多时候,我们的程序会用到第三方没有源代码的模块,有些情况下模块有内存泄露,但是没有证据,又或者VC++ MFC退出提示有内存泄漏,但是信息不足,不好定位是哪个文件哪个函数出问题,我们该怎么办? 这时我们就要依靠无所不能的WinDbg了。

不了解windbg的读者,请见我的另一篇博客《Windows平台的Windbg/x64dbg/OllyDbg调试器

  1.  
    Windows SDK v10
  2.  
    C:Program Files (x86)Windows Kits10Debuggersx64windbg.exe
  3.  
    C:Program Files (x86)Windows Kits10Debuggersx86windbg.exe
  4.  
    gflags.exe和windbg.exe在同一个安装路径

1、先运行Windbg安装目录下的gflags.exe,Image File,Image填exe名字,不要全路径,选上Create user mode stack trace database;

2、准备好Windows系统的环境变量,添加环境变量_NT_SYMBOL_PATH和_NT_ALT_SYMBOL_PATH,而_NT_SYMBOL_PROXY是可选项,非必需。

  1.  
    _NT_SYMBOL_PATH=C:Symbols;srv*C:Symbols*http://msdl.microsoft.com/download/symbols
  2.  
    _NT_ALT_SYMBOL_PATH=cache*C:Symbols
  3.  
    _NT_SYMBOL_PROXY=127.0.0.1:8100

(1)这句话的意思是:指定用于符号解析的符号路径为本地路径C:Symbols,如果找不到就去http://msdl.microsoft.com/download/symbols下载,存放路径是C:Symbols。所以第1次断点调试时,可能需要下载等很久,第2次以后就不会了。

(2)一定要用C:Symbols这个目录,不要用自定义的目录。否则会提示错误,如下:
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll - 

(3)考虑到.pdb符号文件较大,为了给系统盘瘦身,不想把符号文件放在C盘,那就可以采用mklink加入文件链接的方法。用管理员权限打开CMD(windows开始菜单-所有程序-附件-命令提示符-右键,以管理员身份运行),输入命令:

mklink /D C:Symbols E:softwareQtsymbolcache

这样会在C盘建立链接C:Symbols,它实际指向的是E盘自定义路径。

(4)环境变量_NT_SYMBOL_PATH的设置不仅仅适用于WinDbg。实际上,所有调试器(至少Microsoft的VS调试器)都将使用此设置。VS2017的调试选项如图:

之后我用VS调试器,因为第1次调试时已经下载了符号文件到本地,第2次及以后调试时,记得要去掉"Mincrosoft符号服务器"的勾选,然后点击F5进入调试。但是我发现了一个问题,即状态栏每次都提示从服务器下载并加载符合文件,文件很多还很慢。按理说,第1次调试时,符号文件pdb不是已经下载到本地磁盘了吗?怎么又要下载?这是一个潜在的坑:

原来VS调试器运行过程中,它任何时候都会从windows服务器加载;windows符号本地有了还仍然去svr查找;微软服务器符号加载如此之慢,竟然有时快有时慢!详情见《微软符号服务器_NT_SYMBOL_PATH给VS调试带来的隐藏坑

解决方法有以下两种(推荐方法2):

(1)到环境变量里,删除或者重命名_NT_SYMBOL_PATH变量;

(2)到环境变量里,设置_NT_SYMBOL_PROXY,指向一个无效的代理服务器IP和Port;

重启VS,OK!!

3、运行Windbg.exe,(注意,32位程序请使用32位windbg调试,64位程序用64位windbg调试。)

(1)菜单File-Symbol File Path,或者Ctrl+S,弹框,请输入用户程序的.pdb符号文件路径(非必须,如果没有pdb文件则略过该步骤):

C:Usersfirecatsource
eposSmartDispenserDebug

加上之前已配置的环境变量_NT_SYMBOL_PATH,最终的符号文件路径会成为:

C:Usersfirecatsource
eposSmartDispenserDebug;C:Symbols;srv*C:Symbols*http://msdl.microsoft.com/download/symbols

windbg命令行的符号命令介绍:

.sympath #查看符号目录

.reload #重新加载符号目录

!sym noisy #利用 !sym noisy 命令可以清楚发现 Symbols 安装到底在哪里出了问题

!heap #查看堆栈

(2)菜单File-Open Executable-打开需要调试的exe文件

(3)菜单Debug-Go,一步一步得运行

(4)exe在手动关闭退出时windbg会显示内存泄漏:

Detected memory leaks!
Dumping objects ->
{194} normal block at 0x04091C20, 8 bytes long.
 Data: <Ll y    > 4C 6C 86 79 01 CD CD CD 
Object dump complete.
 

可以发现地址0x04091C20就是内存泄漏的地址,泄漏8个字节,但是信息仍不足,不好定位究竟是哪个文件哪个函数出了问题,我们该怎么办?解决办法如下:

通过!heap命令对该地址进行分析,可以发现具体的调用堆栈:

!heap -p -a 0x04091C20

通过这句提示,可以发现问题所在:

TKernel!TCollection_AsciiString::TCollection_AsciiString+0x00000036

欢迎访问姊妹篇

Windows平台的Windbg/x64dbg/OllyDbg调试器简介以及符号文件*.pdb总结

Qt Creator的CDB调试器--使用技巧与心得,重点是Symbols Path设置

---

参考文献

https://blog.csdn.net/antclub/article/details/7488868

windbg调试内存泄漏

使用WinDBG调试内存泄露的问题

Windbg设置了sympath,为什么还提示找不到symbol?

from:https://blog.csdn.net/libaineu2004/article/details/104087514?utm_medium=distribute.pc_relevant_bbs_down.none-task--2~all~sobaiduend~default-2.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task--2~all~sobaiduend~default-2.nonecase

原文地址:https://www.cnblogs.com/lidabo/p/14380726.html