WinDbg 入门三:调试Dump,爆内存的问题

勇哥注:

最近开发的软件遇到一些问题,主要是爆cpu时间,这样的后果是软件运行时间一长就会越跑越慢,最终UI失去响应。

用vs来排除,目前只知道对可疑代码进行失能,再配合任务管理器观察 :cpu使用率, cpu时间,线程,句柄等参数来判断可疑代码是不是有问题。

如果搜索一下网络,貌似这个问题大部分答案只是对线程做sleep,没啥子可用的信息。

因此是时候涨点知识了,我把学习方向放在用WinDbg调试用户模式.net程序上。




(一)什么是dump文件


(1)什么是dump文件

从软件开发的角度上,dump文件就是当程序产生异常时,用来记录当时的程序状态信息(例如堆栈的状态),用于程序开发定位问题。


(2)如何产生dump文件

网络上介绍了好几种方式:


任务管理器

http://blog.csdn.net/whatday/article/details/47275711(该方法已经验证,简单有效)


修改注册表

http://blog.csdn.net/hgy413/article/details/7586957)


程序的方法

对于windows的程序,会注册一个异常处理函数的回调函数,在函数调用MiniDumpWriteDump,当程序异常退出是就会产生dump文件。


(3)为何要使用dump文件

对于发布的现场的软件产品,由于复杂场景的考验,对于在办公室开发的人员很难模拟重现问题,通过对dump文件的调试,对于快速准确的定位问题是一种极为有效的方式


(4)如何利用dump定位源代码

dump文件可以利用WinDbg打开,也可以直接用vs打开,这里需要严格需要的文件:

现场版本dll以及exe文件

编译此版本的pdb文件

将以上文件与dump文件放在一个目录。

然后vs就可以准确定位异常出现在代码中的位置。



(二)查看爆内存的相关指令

!address -summary    ------------ 查看当前 process 的内存占用量,使用 即可

.cls -------------------------------清屏

~ ----------------------------------查看当前程序的所有线程

~0s --------------------------------切换到我们需要调试的原托管线程中

!Threads ---------------------------命令可以查看进程内所有的托管线程,仅仅是托管线程

!dumpheap -stat --------------------统计堆的信息

!dumpheap -type System.String ------查看string类型在堆中的信息.为什是string,是因为在!dumpheap -stat的结果中,发现string占用最内存最多

!gcroot 02029348 -------------------查看内存很高的堆地址, 02029348 是!dumpheap结果中有对string操作的堆最大的Adress

!help gcroot -----------------------查看gcroot的帮助



(三)分析实例一

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> list = new List<string>();

            for (int i = 0; i < int.MaxValue; i++)
            {
                list.Add(string.Join(",", Enumerable.Range(0, 10000)));
            }

            Console.ReadLine();
        }
    }
}


运行后,可以看到报了内存溢出异常。

我们“创建转储文件”

image.png


生成的dump文件有1.7G


image.png

使用指令!address -summary 查看进程消耗的内存

结果如下:

apping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
<unknown>                               332        0`698c9000 (   1.649 GB)  91.78%   82.46%
Free                                    162        0`0cff1000 ( 207.941 MB)           10.15%
Image                                   593        0`0828a000 ( 130.539 MB)   7.09%    6.37%
Stack32                                  30        0`00a00000 (  10.000 MB)   0.54%    0.49%
Heap32                                   35        0`004ab000 (   4.668 MB)   0.25%    0.23%
Stack64                                  30        0`00280000 (   2.500 MB)   0.14%    0.12%
Other                                    11        0`001e0000 (   1.875 MB)   0.10%    0.09%
Heap64                                    7        0`00180000 (   1.500 MB)   0.08%    0.07%
TEB64                                    10        0`00014000 (  80.000 kB)   0.00%    0.00%
TEB32                                    10        0`0000a000 (  40.000 kB)   0.00%    0.00%
Other32                                   1        0`00001000 (   4.000 kB)   0.00%    0.00%
PEB64                                     1        0`00001000 (   4.000 kB)   0.00%    0.00%
PEB32                                     1        0`00001000 (   4.000 kB)   0.00%    0.00%

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE                             425        0`681da000 (   1.627 GB)  90.54%   81.34%
MEM_IMAGE                               593        0`0828a000 ( 130.539 MB)   7.09%    6.37%
MEM_MAPPED                               43        0`02b9b000 (  43.605 MB)   2.37%    2.13%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_COMMIT                              832        0`6d2ab000 (   1.706 GB)  94.93%   85.29%
MEM_FREE                                162        0`0cff1000 ( 207.941 MB)           10.15%
MEM_RESERVE                             229        0`05d54000 (  93.328 MB)   5.07%    4.56%

--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_READWRITE                          375        0`646f5000 (   1.569 GB)  87.33%   78.47%
PAGE_EXECUTE_READ                        82        0`069cf000 ( 105.809 MB)   5.75%    5.17%
PAGE_READONLY                           215        0`01728000 (  23.156 MB)   1.26%    1.13%
PAGE_WRITECOPY                          123        0`00a71000 (  10.441 MB)   0.57%    0.51%
PAGE_READWRITE|PAGE_GUARD                20        0`00032000 ( 200.000 kB)   0.01%    0.01%
PAGE_EXECUTE_READWRITE                   17        0`0001c000 ( 112.000 kB)   0.01%    0.01%

--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
<unknown>                                 0`7dbd9000        0`01f47000 (  31.277 MB)
Free                                      0`5a540000        0`00f70000 (  15.438 MB)
Image                                     0`79310000        0`00f55000 (  15.332 MB)
Stack32                                   0`051a0000        0`000fc000 (1008.000 kB)
Heap32                                    0`01310000        0`000ff000 (1020.000 kB)
Stack64                                   0`00ca0000        0`00035000 ( 212.000 kB)
Other                                     0`01900000        0`00181000 (   1.504 MB)
Heap64                                    0`06aa0000        0`00096000 ( 600.000 kB)
TEB64                                     0`00f38000        0`00002000 (   8.000 kB)
TEB32                                     0`00f3a000        0`00001000 (   4.000 kB)
Other32                                   0`02ee0000        0`00001000 (   4.000 kB)
PEB64                                     0`00f36000        0`00001000 (   4.000 kB)
PEB32                                     0`00f37000        0`00001000 (   4.000 kB)

看到上面 PAGE_READWRITE 行的 (1.569 GB) 吗? 和任务管理器中的内存消耗能对应上。


我们来查看大对象,在托管堆中使用 !dumpheap -stat -min 1024 即可

勇哥敲这条指令后,返回错误:

0:000> !dumpheap -stat -min 1024
No export dumpheap found


敲入指令.loadby sos clr调用sos,又出现错误:

0:000> .loadby sos clr
The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll) failed, Win32 error 0n193
    "%1 不是有效的 Win32 应用程序。"
Please check your debugger configuration and/or network access.


这个原因是程序编译成了32位的,而我当前使用的windbg是64位的,我们要换成32位windb来调试。

在目录下可以找到x86版本。

image.png


干脆两个版本都弄个快捷方式置桌面上。

image.png


继续实验,敲入指令.loadby sos clr

结果还是错误:

0:000> !dumpheap -stat -min 1024
SOS does not support the current target architecture.


这回又是什么鬼呢?


原因在于使用了64位的任务管理器导出了32位进程的dump文件,下面是两个解决方法:

1、使用32位任务管理器,运行:C:\Windows\SysWOW64\taskmgr.exe。

2、使用其它转储工具,比如:ProcessExplorer。


我使用32位任务管理器重新制dump,然后继续。

指令完成无报错。

0:000> .loadby sos clr


继续找大对象,可以看到string对象有16415个。

image.png

接下来可以增加 -type 属性筛选出 >10k 的字符串。

0:000> !dumpheap -type System.String -min 10240

从最后的 !gcroot 看,确实是被 Program.cs:18 行的 List 所持有,到此水落石出。

image.png


--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年3月    »
123
45678910
11121314151617
18192021222324
25262728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864