Windbg程序调试--转载

WinDbg是微软发布的一款相当优秀的源码级(source-level)调试工具,可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。

WinDbg是微软很重要的诊断调试工具: 可以查看源代码、设置断点、查看变量, 查看调用堆栈及内存情况。

? 调试应用程序(用户模式 user mode)

? 调试操作系统及驱劢程序(内核模式 kernel mode)

? 调试非托管程序(native program)

? 调试托管程序(managed program)

? 实时调试 (JIT: Just in time)

? 事后调试 (postmortem debugging)

使用WinDbg可以解决线上.NET应用程序的如下问题:

◆ 内存高

◆ CPU高

◆ 程序异常

◆ 程序Hang死

在生产环境下进行故障诊断时,为了不终止正在运行的服务或应用程序,有两种方式可以对正在运行的服务或应用程序的进程进行分析和调试。

一、用WinDbg等调试器直接attach到需要调试的进程,调试完毕之后再detach即可。但是这种方式有个缺点就是执行debugger命令时必须先break这个进程,执行完debug命令之后又得赶紧F5让他继续运 行,因为被你break住的时候意味着整个进程也已经被你挂起。另外也经常会由于First Chance Excetpion而自动break,你得时刻留意避免长时间break整个进程。所以这样的调试方式对时间是个很大的考验,往往没有充裕的时间来做仔细分析。

二、在出现问题的时候,比如CPU持续长时间100%,内存突然暴涨等非正常情况下,通过对服务进程snapshot抓取一个dump文件,完成dump之后先deatch,让进程继续运行。然后用windbg等工具来分析这个抓取到的dump 文件。所以我们一般采用这种方式来进行调试排错。

设置符号文件目录

符号文件包含了相关二进制文件的调试信息以.pdb戒.dbg为扩展名。WinDbg使用符号文件来确定调用栈,堆及其他重要信息。

配置WinDbg的符号文件路径

WinDbg符号文件路径搜索的两个位置:环境变量中的_NT_SYMBOL_PATH设置及WinDbg中的"symblos file path";

设置srv*x:/symbols_folder*http://msdl.microsoft.com/download/symbols 路径是保证我们能快速正确使用windbg的法。

1、运行WinDbg->File->Symbol File Path->按照下面的方法设置_NT_SYMBOL_PATH变量:

在弹出的框中输入"C:\ Symbols; SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols"(按照这样设置,WinDbg将先从本地文件夹C:\ Symbols中查找Symbol,如果找不到,则自动从MS的Symbol Server上下载Symbols)。另一种做法是从这个Symbol下载地址中http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx,下载相应操作系统所需要的完整的Symbol安装包,并进行安装,例如我将其安装在D:\WINDOWS\Symbols,在该框中输入"D:\WINDOWS\Symbols"。(这里要注意下载的Symbols的版本一定要正确

2、在控制板的系统中设置一个系统变量_NT_SYMBOL_PATH 为

SRV*c:\symbols*http://msdl.microsoft.com/download/symbols

极速双机调试

双机调试的时候,不管是Windbg+vmware,还是Windbg+1394,其调试速率都是相对比较低的,有时候执行一条p命令,Windbg的状态都会BUSY..好久...
VirtualKD可以完美的解决这一问题。
VirtualKD主要是用来提高当使用vmware或virtualBox进行windows内核调试时的速率。以前的双机标准调试方法是利用虚拟COM串口,其速率很低。
通常,通过虚拟COM串口进行调试包括以下步骤:
1.windows使用虚拟COM串口和host主机之间进行数据交换;
2.WinDbg/KD使用VM提供的一个PIPE管道来与目标调试机进行通信。
这里最弱的连接是虚拟COM串口,其传输速率仅为:115200 baudrate,等效于115200 bit per second,也就是大约10KB/S的传输速率。VirtualKD取代了虚拟COM串口的功能,极大的提高了数据交换速率,可达6MB/S,但是官方给出的用!irpfind命令测试的话,vmware平台可达150KB/S,不过已经比虚拟COM串口快了15倍了。具体的效果只有在调试过程当中,才会体会到 -:) 事实上,VirtualKD的主要原理是,利用KD的扩展DLL功能,并且向虚拟机patch一个进程,二者通过pipe来进行通信。
使用方法:
1.配置方法可简单,可复杂。简单的方法有自动化,复杂的方法有手动配置。手动方法分为动态patch和静态patch两种,具体的可参考官网。http://virtualkd.sysprogs.org/
2.现在只说明下自动安装的情况,目标机为vmware,若是VirtualBox,则稍有改动
下载VirtualKD安装包,解压后,父目录下virtualKD2.2下有一个target目录,将该target目录copy到虚拟机,点击target/vminstall.exe 运行,然后直接安装即可。如图1所示,vminstall.exe会自动检测虚拟机的内核版本,因为我的目标机是wrk 的内核,故显示:wrk debug【VirtualKD】,当然,你也可以将显示的字符串修改后,再点击安装。

当目标机为XP系统的时候,情况如图2所示:
 
(图2)

选择install以后,按照提示直接重启。
接着,在host主机端开启vmmon.exe程序即可(记着,vmmon程序要始终开启着),该程序会自动检测到虚拟机当中正在运行的操作系统。简单的设置下windbg的路径和启动方式(自动/手动),那么一切就OK了。虚拟机启动的时候,windbg调试机就自动或手动挂接上了。如图:

其实配置过程非常简单。这里写的比较啰嗦了,主要是自己第一次配置的时候,没好好读说明书,结果手动配置,浪费了时间;后来选择vminstall.exe自动安装,忘记了设置Debugger path..又浪费了时间去检查。
最终的结论是,使用VirtualKD代替了传统的虚拟COM串口以后,调试速度是飞一般的快。
接受新事物总是好的,认知的过程总是有点小曲折,不过目标对象是多么简单!!!

========================windows 7本地内核调试================

使用VistaLKD 如下图

dump文件获取

dump文件是进程的内存镜像。可以把程序的执行状态,即当时程序内存空间数据通过调试器保存到dump文件中。

1、利用WinDbg里的adplus来获取dump文件

Adplus.vbs 是一个Visual Basic Script 文件,Adplus 主要用来生成内存转储文件 (dump file),内存转储文件适用于不能实时调试的情况下。在WinDbg安装目录里可以找到adplus.vbs,使用adplus.vbs生成dump文件,

adplus -hang -o d:\dump -p 1234

其中hang表示附加到进程,如果是crash,则为目标进程崩溃的时候抓取,-o后面的参数表示dump文件存到位置,-p后面的数字为进程的PID,也可以是-pn后面跟进程名称,如:adplus.vbs -hang -pn ConsoleWindbg.exe -o D:\dump

2、使用Debug Diagnostic Tool(DebugDiag)工具获取dump文件

下载Debug Diagnostic Tool然后进行安装,打开该工具,Debug Diagnostic Tool可以选择不同的规则来进行dump文件。可以根据程序崩溃时捕获dump文件,也可以根据性能指标来进行捕获,如CPU过高,死锁,HTTP响应时间过程等参数。如下图:

也可以找到对应的进程,通过如下方法进行捕获。此种方式获取的dump文件放到C:\Program Files\DebugDiag\Logs\Misc下。

3、使用.dump命令

1) 打开WinDBG—>File—>Attach to a Process,然后选择将之要进行捕获的进程。如我们这里要对ConsoleWindbg.exe进程产生dump文件。选择后如图:

2)在上图红色区域的输入框内输入产生dump 文件的命令 .dump 。可以选择不同的参数来生成不同类型的dump文件。

选项(1): /m

命令行示例.dump /m D:/dump/myapp.dmp

注解: 缺省选项,生成标准的minidump, 转储文件通常较小,便于在网络上通过邮件或其他方式传输。 这种文件的信息量较少,只包含系统信息、加载的模块(DLL)信息、 进程信息和线程信息。

选项(2): /ma

命令行示例.dump /ma D:/dump/myapp.dmp

注解: 带有尽量多选项的minidump(包括完整的内存内容、句柄、未加载的模块,等等),文件很大,但如果条件允许(本机调试,局域网环境), 推荐使用这中dump。

选项(3):/mFhutwd

命令行示例.dump /mFhutwd D:/dump/myapp.dmp

注解:带有数据段、非共享的读/写内存页和其他有用的信息的minidump。包含了通过minidump能够得到的最多的信息。是一种折中方案。

4、使用ProcDump工具

Procdump是一个轻量级的命令行工具, 它的主要目的是监控应用程序的CPU异常动向, 并在此异常时生成crash dump文件, 供研发人员和管理员确定问题发生的原因。你还可以把它作为生成dump的工具使用在其他的脚本中。有了它, 就完全不需要在同一台服务器上使用诸如32位系统上的Debug Diag 1.1或是64位系统上的ADPlus了。

Procdump下载:http://technet.microsoft.com/en-us/sysinternals/dd996900

procdump -ma -c 50% -s 3 -n 2 5844 (Process Name or PID) -o c:\dumpfile

-ma 生成full dump, 即包括进程的所有内存. 默认的dump格式包括线程和句柄信息。

-c 在CPU使用率到达这个阀值的时候, 生成dump文件。

-s CPU阀值必须持续多少秒才抓取dump文件。

-n 在该工具退出之前要抓取多少个dump文件。

-o dump文件保存目录。

技术术语

GC Heap:用于存储对象实例,受 GC 管理

Loader Heap:分为 High-Frequency Heap 、 Low-Frequency Heap 和 Stub Heap ,不同的 heap 又存储不同的信息。 Loader Heap 中最重要的信息是元数据 (MetaData) 相关的信息,也就是 Type 对象,每个 Type 对象在 Loader Heap 上体现为一个 Method Table , Method Table 中记录了存储的元数据信息,如基类型、静态字段、实现的接口、所有的方法等。 Loader Heap 的生命周期为从 AppDomain 创建到卸载。

MethodTable: 我们知道每种type可以有多个instance,每个instance,其每个field可以享有独立的space,而对于type的method提供一个公共的method入口地址。也就是说不管多少个相同类型的instance,其都指向了同一个同一的函数入口地址。在这个函数入口地址描述表中记录了各个函数的入口地址。而MethodTable就有点类似的作用。不过所有Assembly都是自描述的,因此我们可以从MethodTable中,可以知道相应的instance。因此通过相应的debug命令!dumpheap -mt MTAddress可以知道在MethodTable中相关联的所有instance了。

Finalization 原理

通过WinDbg分析dump文件

通过上面步骤,我们生成了dump文件,接下来我们就可以使用WinDbg工具对生成的dump文件进行分析。

案例:

建立控制台应用程序,代码如下:

namespace ConsoleWindbg

{

class Program

{

private static List<User> list =new List<User>();

static void Main(string[] args)

{

MemeryLeakProc();

Console.ReadLine();

}

private static void MemeryLeakProc()

{

string str = "aaa";

while (true)

{

for (int i = 0; i < 100 * 1024; i++)

{

str += "bbb" + i;

User u = new User();

u.Age = i;

u.Name = "UserName" + i;

list.Add(u);

}

Thread.Sleep(1000);

}

}

}

public class User

{

public int Age { set; get; }

public string Name { set; get; }

}

}

编译,运行,按照上面的步骤产生dump文件。然后使用WinDbg打开dump文件。

红色标注区域显示了dump文件获取的一些环境信息,如:当前系统信息,程序运行时间,符号文件的路径等。

WinDbg调试托管程序时需用SOS扩展(SOS.dll), SOS 调试扩展(SOS.dll) 通过提供有关内部公共语言运行时(CLR) 环境的信息,帮助您在WinDbg.exe 调试器和Visual Studio 中调试托管程序。SOS.dll安装在.Net Framewok 目录底下C:\Windows\Microsoft.NET\Framework\vx.x.xxxxx。WinDbg调用SOS.dll的语法:

SOS.dll 在.Net Framewok 目录底下,在WinDbg的命令行输入:

.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll?

拷贝SOS.dll 到windbg目录底下,注意拷贝的Framework版本必须和你要调试的目标程序所使用的版本一致,否则调试信息就不能正确显示出来。如果你同时工作在两个版本的Framework的话,可以SOS文件重命名为SOS<version>.dll或者直接将它们放入不同的文件夹下面。可以使用如下命令:

.load sos.dll

.loadby sos mscorwks  [.Net 3.5版本及以下]

?     检查SOS.dll是否已经装载

.chain

内存过高问题

内存过高问题初判定,内存泄漏可以通过以下两种方式通过性能监视器来基本判断属于那种类型的内存泄露。

A、非托管程序的症状 (Perfmon工具)

Process\Private Bytes 增加

.NET CLR Memory\# Bytes in all heaps不增加

B、托管程序的症状 (Perfmon工具)

Process\Private Bytes增加

.NET CLR Memory\# Bytes in all heaps也增加

本例属于托管程序症状,通过Perfmon工具已经得到判断,此步骤略。

  1. 测试程序

    BuggyBits(http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-components-postattachments/00-07-43-14-54/BuggyBits.zip

    下载后部署到本机,产生压力:

    tinyget -srv:dbg.buggybit.com -uri:/Links.aspx -loop:4000

观察进程中w3wp进程,发现内存增长很快,大约该进程内存增长到700M时,抓取一个hang dump。

  1. 与内存操作相关命令

    !eeheap –gc:正是查看GC堆得命令,查看GC堆上的内存占用是多大

    !eeheap –loader:正是查看Loader堆得命令

    !dumpheap –stat:就是GC堆上的统计,就看看GC堆上存活的对象是那些

    !dumpheap -mt <<MethodTable address>>:查看该地址上的对象

    !dumpheap –type:通过 type 参数查看内存中指定类型的对象

    !gcroot +对象地址:这个命令就可以得到这个对象的"根"

    !objsize +对象地址:查看对象占用多大的内存

    !name2ee TestClass.exe TestClass.Program.test ://显示test方法相关的地址

    !dumpmt -md 00976d48 ://得到类的成员函数详细信息

    !dumpmt:找到相关MethodTable处的相关信息。

    !dumpmd:根据MethodDesc找到相关模块信息,比如MethodTable.

    !dumpdomain:显示所有域里的程序集,或者根据参数获取指定域。

    !dumpil 00973028:// 显示这个方法被编译器编译之后的IL代码

    !dumpobj(do) 012a3904: //显示一个对象的具体内容,看对象里面有什么,值是什么

    !dumpmodule 1ee30010:查看某个模块的详细信息

    !DumpArray: //查看数组信息

  2. 分析过程

3.1、运行命令!eeheap –gc查看GC堆的情况,发现GC Heap大小为720多兆,所以我们重点分析托管堆的情况。从运行结果可以看到GC Heap中g0,g1,g2和LOH的堆情况,以及该GC Heap中所分配的段情况。

可以运行!dumpheap -mt 0c3b0038 0c3b0048命令查看LOH堆中大对象的情况。从统计结果看,LOH堆中没有大的对象存在。同理我们也可以统计各个段上对象的情况。

3.2、接下来看下heap中对象的一些情况,运行命令!dumpheap –stat。统计堆上所有对象的情况。统计项包括MT(Method Table),Count对象个数,TotalSize对象所占用的大小。Count与TotalSize按照升序统计。

最终我们发现,System.Char[]占用内存最多,大概720M,同时有36088个System.Char[]对象。

这里我们做个推理,通过!dumpheap –stat统计到的System.Char[]的个数,应该与在3.1中显示的各个段中System.Char[]个数之和相等。即如果对3.1中统计到的各个段进行!dumpheap –stat <startAddress> <endAddress>统计,各个段中统计到的System.Char[]个数之和应该与3.2中统计到的结果相同,通过验证发现,结论正确。

3.3、过滤一下,看看10K以上大小的字符串,运行命令:!dumpheap -mt 6f021ee4 -min 10000。10K以上的有35996个。

3.4、随便找个对象看下引用关系,运行!gcroot 36278028,结果如下:

通过结果发现,Link引用了这个字符串。而且我们看到,link是在Finalizer Queue中的。有关Finalizer Queue可以参考.net Finalization原理。

3.5、通过运行命令! Finalizequeue 查看Finalizer Queue队列的情况。

00b740fc 35987 575792 Link

一共有35987个Link对象存在于Finalizer Queue中,因此可以判定,Link类一定是显示的实现了Finalize方法。

3.6、查看该方法,代码如下:

  ~Link()

  {

  //some long running operation when cleaning up the data

  Thread.Sleep(5000);

}

3.7、接下来我们看下Link对象的结构,可以通过3.4步骤中运行出来的结果找到对应那个Link对象的地址,通过运行命令!do 36277ffc 来查看,当然也可以通过找到Link对象的MT,通过查看!dumpheap –mt <MTAddress>上的所有Link对象,找到其中一个地址,在通过!do <address>来查看。

据此发现,Link应该有url和name两个属性。通过!objsize 362a66ec查看url对象的大小为20k,且是StringBuilder类型的。

sizeof(362a66ec) = 20040 ( 0x4e48) bytes (System.Text.StringBuilder)

3.8、查看代码

public Link(string name, string url)

  {

  this.name = name;

  this.url.Append(url);

  }

会引起垃圾回收器托管堆速度的几个问题

? 1、分配太频繁

? 2、预先分配空间

? 3、太多的引用(pointers)和根(roots)

? 4、太多的对象实例有很长的生命期

? 5、太多的定位对象实例(pinned)

6、有终结函数的对象实例

?         占用更多资源

?         更长的生命期

?         两次才能回收

?         垃圾回收器(GC)只有一个线程来运行终结函数

?         有时这个线程会很慢戒堵塞(blocked)

CPU/异常操作相关命令

查看引起CPU过高命令比如:

!threadpool:查看线程池CPU使用量,我认为WEB的比如iis应用程序池进程w3wp如果CPU使用过高,那查看线程池命令肯定看的出来过高,这个是我自己的理解,c/s的就不一定了。

!threads:查看所有托管线程情况

!clrstack:到具体某个线程后,本线程托管代码的调用栈情况

~* e !clrstack:所有线程托管代码的调用栈情况

!runaway:查看线程占用CPU时间,可以从中找到哪个线程占用时间更高。

~number s:number为具体哪个线程的ID。

!dumpstackobjects(!dso):本线程调用栈所有对象实例

!dumpdomain:显示所有域里的程序集,或者根据参数获取指定域。

!savemodule:根据具体程序集地址,把当前程序集的代码生成到指定文件

!PrintException:显示在当前线程上引发的最后一个异常错误信息

!StopOnException:在指定异常错误信息停止运行

!VerifyHeap:检查垃圾回收器堆中是否有损坏迹象,并显示找到任何错误

!SyncBlk –all:显示所有SyncBlock 结构情况

4.1、产生压力

TinyGet.exe -srv:dbg.buggybit.com -uri:/AllProducts.aspx -threads:5 -loop:1

4.2、通过Procdump抓取三个dump文件

procdump -ma -c 50% -s 2 -n 3 w3wp.exe -o d:\dump

4.3、打开这三个dump,加载sos之后,分别查看!runaway的输出。

第一个dump输出:

0:023> !runaway

User Mode Time

Thread Time

23:14c8 0 days 0:00:06.817

22:1b74 0 days 0:00:06.084

31:ba8 0 days 0:00:02.823

30:680 0 days 0:00:02.823

33:25c 0 days 0:00:00.280

35:13c8 0 days 0:00:00.218

第二个dump输出:

0:023> !runaway

User Mode Time

Thread Time

23:14c8 0 days 0:00:12.792

22:1b74 0 days 0:00:11.918

31:ba8 0 days 0:00:04.009

30:680 0 days 0:00:03.712

35:13c8 0 days 0:00:01.965

33:25c 0 days 0:00:01.887

34:14e4 0 days 0:00:00.514

第三个dump输出:

0:023> !runaway

User Mode Time

Thread Time

23:14c8 0 days 0:00:18.969

22:1b74 0 days 0:00:17.160

31:ba8 0 days 0:00:05.382

30:680 0 days 0:00:04.804

35:13c8 0 days 0:00:03.151

33:25c 0 days 0:00:02.792

34:14e4 0 days 0:00:01.185

4.4、从上面三个输出结果发现只有22,23,30,31号线程一值在增长。且22,23线程增长的速度较快。查看三个dump的!threadpool基本都在90%以上。

4.5、运行!threads查看当前都有哪些线程。

不知道为什么并没有找到22,23线程,有30,31线程号。

4.6、切换到30线程中,运行命令~30s

4.7、查看当前线程的调用栈情况,运行!clrstack

发现System.String.Concat方法,这是典型的字符串拼接的函数,通过调用关系发现应该是在AllProducts.Page_Load(System.Object, System.EventArgs)方法中。

4.8、查看代码

protected void Page_Load(object sender, EventArgs e)

{

DataTable dt = ((DataLayer)Application["DataLayer"]).GetAllProducts();

string ProductsTable = "<table><tr><td><B>Product ID</B></td><td><B>Product Name</B></td><td><B>Description</B></td></tr>";

foreach (DataRow dr in dt.Rows)

{

ProductsTable += "<tr><td>" + dr[0] + "</td><td>" + dr[1] + "</td><td>" + dr[2] + "</td></tr>" ;

}

ProductsTable += "</table>";

tblProducts.Text = ProductsTable;

}

这里面有一个循环的方法,然后针对输出的DataTable,进行了大量的String.Concat操作。

1!address

!address 扩展显示目标进程或目标机使用的内存信息。

这个学习起来比较简单:我们直接使用!address -?就可以找到它的使用说明:

给个例子:

[cpp] view plaincopy

  1. 0:001> !address -?  
  2. !address                 - prints information on the entire address space  
  3. !address -?              - prints this help  
  4. !address <address>       - prints available information about the region  
  5.                            of the address space containing this address  
  6. !address -summary        - prints only summary information  
  7. !address -RegionUsageXXX - fiters the output limiting the dispaly to one  
  8.                            of the following types:  
  9.   RegionUsageIsVAD            - `busy` region that could be charcterized better  
  10.                                  this includes Virtual-Alloc-ed blocks, SBH heap,  
  11.                                  memory from custom allocators, etc  
  12.   RegionUsageFree             - availalble (neither committed nor reserved) region  
  13.   RegionUsageImage            - region used by mapped images of binaries  
  14.   RegionUsageStack            - stack of threads  
  15.   RegionUsageTeb              - TEB of threads   
  16.   RegionUsageHeap             - region in used by a heap  
  17.   RegionUsagePageHeap         - region in use by full page-heap  
  18.   RegionUsagePeb              - PEB of the process  
  19.   RegionUsageProcessParametrs - parameters of the process  
  20.   RegionUsageEnvironmentBlock - environment block  

那么一个个说明吧:

!address显示整个地址空间和使用摘要的信息

这个太长了,它会把从0-7ffefff的全打印出来,熟悉核心编程的应该知道,正常的2G用户地址空间是这样划分的:0-ffff为64K空指针区,1000-7ffeffff为用户模式分区

之后64K为禁入分区,之后就是内核模式分区,要看它们的信息,需要用到以下的表,


Filter 值


显示的内存区域


RegionUsageIsVAD


"busy" 区域。包括所有虚拟分配块、SBH堆、自定义内存分配器(custom allocators)的内存、以及地址空间中所有属于其他分类的内存块。


RegionUsageFree


目标的虚拟地址空间中所有可用内存。包括所有非提交(committed)和非保留(reserved)的内存。


RegionUsageImage


用来映射二进制映像的内存区域。


RegionUsageStack


用作目标进程的线程的堆栈的内存区域。


RegionUsageTeb


用作目标进程中所有线程的线程环境块(TEB)的内存区域。


RegionUsageHeap


用作目标进程的堆的内存区域。


RegionUsagePageHeap


用作目标进程的整页堆(full-page heap)的内存区域。


RegionUsagePeb


目标进程的进程环境块(PEB)的内存区域。


RegionUsageProcessParametrs


用作目标进程启动参数的内存区域。


RegionUsageEnvironmentBlock


用作目标进程的环境块的内存区域。

下面这些Filter值按照内存类型来指定内存。


Filter 值


显示的内存类型


MEM_IMAGE


映射的文件属于可执行映像一部分的内存。


MEM_MAPPED


映射的文件不属于可执行映像一部分的内存。这种内存包含哪些从页面文件映射的内存。


MEM_PRIVATE


私有的(即不和其他进程共享)并且未用来映射任何文件的内存。

下面的Filter 值按照状态来指定内存:


Filter 值


显示的内存状态


MEM_COMMIT


当前已提交给目标使用的所有内存。已经在物理内存或者页面文件中为这些内存分配了物理的存储空间。


MEM_RESERVE


所有为目标以后的使用保留的内存。这种内存还没有分配物理上的存储空间。


MEM_FREE


目标虚拟地址空间中所有可用内存。包括所有未提交并且未保留的内存。该Filter 值和RegionUsageFree一样。

时间: 2024-11-04 11:21:31

Windbg程序调试--转载的相关文章

调试.NET程序OutOfMemoryException (转载)

原文地址:http://blog.csdn.net/directionofear/article/details/8009427 应用程序调试,需要有个常规的调试思路,应对各类问题最基本的调试手段是什么,不能一头雾水的上手而乱了阵脚,而且根据经验统计这些基本的步骤可以解决大多数的问题. 问题分类 第一种,应用程序不工作了. 第二种,应用程序反应很慢. 对于这样简单的描述我们一般需要进一步了解更多信息,比如 问题最直接的表现是什么? 浏览器显示网页报错信息  Web Service调用报错信息 是

.NET应用程序调试—原理、工具、方法

阅读目录: 1.背景介绍 2.基本原理(Windows调试工具箱..NET调试扩展SOS.DLL.SOSEX.DLL) 2.1.Windows调试工具箱 2.2..NET调试扩展包,SOS.DLL.SOSEX.DLL 2.3.调试系统的基本流程及架构(.NETDAC概念.mscordacwks.dll) 2.4.VisualStudio中集成扩展调试(更加细粒度的调试程序) 3.调试程序类型(客户端程序.服务端程序) 4.调试方式及场景 4.1.本机调试(Attach Process,调试器启动

Chisel辅助iOS 应用程序调试,MusicApp模仿酷狗4.0 UI框架

本文转载至 http://www.cocoachina.com/ios/20140825/9446.html Chisel Chisel集合了大量的LLDB 命令来辅助iOS 应用程序调试,并支持添加本地和自定义的命令.以下是其中所包含的一些命令,并对其适用于iOS还是OS X进行了区分: M13ProgressSuite 该项目包含了多种不同的风格的进程指示图,比如普通圆环形.分段圆形加载.圆形饼图加载以及条形加载等等,比如其中UINavigationBar的进程动画非常像苹果的Messag

Windows程序调试系列: 使用VC++生成调试信息 转

Windows程序调试系列: 使用VC++生成调试信息 ZhangTao,[email protected], 译自 “Generating debug information with Visual C++”,Oleg Starodumov 出处: http://www.cnblogs.com/itrust/archive/2006/08/17/479603.aspx 引子 当我们使用调试器来调试程序时,我们希望能够单步调试到源代码中,在代码中设置断点,观察变量的值(包括用户自定义的复杂类型的

【转】iOS平台的应用程序调试与分析

转自:看雪学院的文章 iOS平台的应用程序调试与分析 作者:zhuliang转载请保证文章完整并注明来自看雪或cd-team 本文阐述如何在iOS平台上对应用程序进行调试与分析,旨在指导新手分析iOS程序,高手请无视.内容包括软件硬件的准备.代码的解密.符号信息的获取.用gdb调试等,最后以京东LeBook为例子进行演示.1.为什么要进行调试与分析研究iOS程序有很多用处,比如:找bug或者漏洞,想知道某程序有没有漏洞或者bug.某程序能实现某功能,我想知道如何实现,如ios6发短信功能,还有比

windbg远程调试

1, A,调试机. B,被调试机. 2, 在B机上安装windbg,公共符号文件,程序的PDB都要复制过来. 公共符号文件位置设置在于A机相同的位置. windbg–server tcp:port=5699 xxx.exe 3, 在A机上 windbg –remote tcp:port=5699,server=192.168.0.233 .reload F5 windbg远程调试,布布扣,bubuko.com

使用WinDbg内核调试[转]

Technorati 标签: windbg,内核调试 WINDOWS调试工具很强大,但是学习使用它们并不容易.特别对于驱动开发者使用的WinDbg和KD这两个内核调试器(CDB和NTSD是用户态调试器). 本教程的目标是给予一个已经有其他调试工具使用经验的开发者足够信息,使其能通过参考WINDOWS调试工具的帮助文件进行内核调试. 本文将假定开发者熟悉一般WINDOWS操作系统和进程的建立过程. 本文的重点是集成内核模式和用户态模式的图形化调试器WinDbg.KD在脚本和自动化调试中更有用,并且

【系统篇】从int 3探索Windows应用程序调试原理

探索调试器下断点的原理 在Windows上做开发的程序猿们都知道,x86架构处理器有一条特殊的指令——int 3,也就是机器码0xCC,用于调试所用,当程序执行到int 3的时候会中断到调试器,如果程序不处于调试状态则会弹出一个错误信息,之后程序就结束.使用VC开发程序时,在Debug版本的程序中,编译器会向函数栈帧中填充大量的0xCC,用于调试使用.因此,经常我们的程序发生缓冲区溢出时,会看到大量的“烫烫烫…”,这是因为“烫”的编码正是两个0xCC. 那么?为什么int 3可以让程序中断到调试

微信小程序调试之【不在以下合法域名列表中】

在微信小程序中进行网络通信,只能和指定的域名进行通信.目前,微信小程序提供如下四种类型的网络请求. 普通HTTPS请求(wx.request) 上传文件(wx.uploadFile) 下载文件(wx.downloadFile) WebSocket通信(wx.connectSocket) 目前,无论上述哪一种请求方式,都有次数限制.本文记录的是,我在使用豆瓣论坛API请求时,遇到的错误截图及解决办法.简记如下: 一.问题截图 小程序调试中,遇到如下错误提示: "xxx不在以下合法域名列表中 ,请参