`
chinamming
  • 浏览: 151499 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

调试Bug的神兵利器:通过WinDbg条件断点收集Log

 
阅读更多

前段时间花了几天一直在用WinDbg调试一个比较棘手的Bug。这个Bug是C# Team那边发现的,他们的Testcase跑大概10分钟左右会出一个在CLR内部的ASSERT。比较难调试的主要原因在于ASSERT表明一个全局的数据结构出现了问题,本来不应该用完的数组却已经用完了(因为按照设计,这个数组是边使用边清理的,是不会用完的)。初步想到的有下面几种方案来调试:

1. 设置数据断点

2. 一步一步调试

3. 添加Log代码

设置数据断点的主要问题是不太好确定到底是因为什么原因导致的数据结构问题,而且因为是数组被用完,很难将是到底是哪一个数组元素的加入导致了数组被全部占用,因此无法通过设置数据断点的方法来调试。一步一步的调试显然也没法解决问题,因为这个Testcase本身要跑十分钟,可以想象单步调试运行十分钟的程序会花费多长时间。因此两个方案都被我否决。添加Log代码其实是可以的,只是需要修改代码,每次修改之后需要重新编译代码,然后需要在目标机器上安装,而且C#使用的CLR的Branch并非我们正在开发的Branch,需要重新下载源代码,相对比较麻烦。最后为了解决这个问题,我采取的方法是使用WinDbg的条件断点+Log的方式。大致的方法如下:

第一步:在一个或者多个可疑处设置断点

bu[ID] [Options] [Address [Passes]] ["CommandString"]

bu是WinDbg中的设置Unresolved Breakpoints命令,用起来比较方便,我比较喜欢用。address就是你所要断的代码地址,可以是函数开始,也可以是某一行。Command非常重要,它表示了WinDbg在每次断到address的时候都要执行的命令,不同命令用分号隔开,如:

.echo [Function A]; dv this; kb; g

这几条命令意思是:打印[Function A],打印this指针的值,打印当前调用栈,然后继续执行。大家可以根据实际情况添加一些其他命令打印一些自己所需要的信息。通过上面这套命令打印的内容大致如下:

[FunctionA]

this = 0xABCDEFG

module!FuncA

module!FuncB

module!FuncC

可以看出,这条断点如果反复被断,那么在WinDbg的命令窗口中便会把每次断点被Hit的相关信息通过刚才定义的命令打印出来。如果定义了很多这样的断点,那么在命令窗口中就会把整个程序执行的情况打印出来,起到Log的作用,而且可以显示调用栈等信息,比一般的Log要强大许多。

第二步:设置Log

缺省情况下,WinDbg的Buffer大小是有限的,如果程序运行时间比较长,那么Buffer可能会不够,我们通过条件断点打出的信息会被截断。幸好,WinDbg提供了将命令窗口的内容输出到Log中的功能。选择Edit->Open/Close Log File菜单项,WinDbg会显示如下对话框:

clip_image002

在这个对话框里面输入你想要保存的Log文件名即可。如果是添加新的内容而不是覆盖原有的,则勾上Append。

第三步:分析Log

当获得了Log信息之后,下一步就需要分析Log的内容了,这是一件需要耐心、对数据的敏感、以及一点点运气的事情。分析的时候可能发现Log的信息不足,这时就需要添加新的断点或者修改打印的信息,重新收集Log,再加以分析,直到Log信息足够为止。这时WinDbg设置条件断点的优势就出来了,因为不需要修改代码,编译代码,部署代码这样的一个过程,而是只需要键入不同的命令而已。经过几次调整断点位置和打印的信息并重新收集Log,我最终通过分析发现这个Bug是只有可能在特定情况下RCW没有被GC,并且创建线程退出的时候才会出现,具体的内容因为涉及到.NET 4.0中还没有发布的新功能,这里就不多说了。可以看到,如果采用常规的方法,对于这种在特定的条件下才会重现的问题是很难发现的。

总之,使用WinDbg来设置条件断点,打印相关信息,并且输出到Log文件是一种非常强大的调试方法,可以调试一些非常复杂的Bug,而且具有不需要修改代码的灵活性,可以自由定义自己想需要打印的信息和断点设置的位置,主要的缺点是方法稍显复杂,不过如果适应了之后还是很方便的。我强烈推荐大家在遇到比较复杂的Bug的时候,可以尝试使用一下这种方法,可能具有意想不到的效果哦。

前段时间花了几天一直在用WinDbg调试一个比较棘手的Bug。这个Bug是C# Team那边发现的,他们的Testcase跑大概10分钟左右会出一个在CLR内部的ASSERT。比较难调试的主要原因在于ASSERT表明一个全局的数据结构出现了问题,本来不应该用完的数组却已经用完了(因为按照设计,这个数组是边使用边清理的,是不会用完的)。初步想到的有下面几种方案来调试:

1. 设置数据断点

2. 一步一步调试

3. 添加Log代码

设置数据断点的主要问题是不太好确定到底是因为什么原因导致的数据结构问题,而且因为是数组被用完,很难将是到底是哪一个数组元素的加入导致了数组被全部占用,因此无法通过设置数据断点的方法来调试。一步一步的调试显然也没法解决问题,因为这个Testcase本身要跑十分钟,可以想象单步调试运行十分钟的程序会花费多长时间。因此两个方案都被我否决。添加Log代码其实是可以的,只是需要修改代码,每次修改之后需要重新编译代码,然后需要在目标机器上安装,而且C#使用的CLR的Branch并非我们正在开发的Branch,需要重新下载源代码,相对比较麻烦。最后为了解决这个问题,我采取的方法是使用WinDbg的条件断点+Log的方式。大致的方法如下:

第一步:在一个或者多个可疑处设置断点

bu[ID] [Options] [Address [Passes]] ["CommandString"]

bu是WinDbg中的设置Unresolved Breakpoints命令,用起来比较方便,我比较喜欢用。address就是你所要断的代码地址,可以是函数开始,也可以是某一行。Command非常重要,它表示了WinDbg在每次断到address的时候都要执行的命令,不同命令用分号隔开,如:

.echo [Function A]; dv this; kb; g

这几条命令意思是:打印[Function A],打印this指针的值,打印当前调用栈,然后继续执行。大家可以根据实际情况添加一些其他命令打印一些自己所需要的信息。通过上面这套命令打印的内容大致如下:

[FunctionA]

this = 0xABCDEFG

module!FuncA

module!FuncB

module!FuncC

可以看出,这条断点如果反复被断,那么在WinDbg的命令窗口中便会把每次断点被Hit的相关信息通过刚才定义的命令打印出来。如果定义了很多这样的断点,那么在命令窗口中就会把整个程序执行的情况打印出来,起到Log的作用,而且可以显示调用栈等信息,比一般的Log要强大许多。

第二步:设置Log

缺省情况下,WinDbg的Buffer大小是有限的,如果程序运行时间比较长,那么Buffer可能会不够,我们通过条件断点打出的信息会被截断。幸好,WinDbg提供了将命令窗口的内容输出到Log中的功能。选择Edit->Open/Close Log File菜单项,WinDbg会显示如下对话框:

clip_image002

在这个对话框里面输入你想要保存的Log文件名即可。如果是添加新的内容而不是覆盖原有的,则勾上Append。

第三步:分析Log

当获得了Log信息之后,下一步就需要分析Log的内容了,这是一件需要耐心、对数据的敏感、以及一点点运气的事情。分析的时候可能发现Log的信息不足,这时就需要添加新的断点或者修改打印的信息,重新收集Log,再加以分析,直到Log信息足够为止。这时WinDbg设置条件断点的优势就出来了,因为不需要修改代码,编译代码,部署代码这样的一个过程,而是只需要键入不同的命令而已。经过几次调整断点位置和打印的信息并重新收集Log,我最终通过分析发现这个Bug是只有可能在特定情况下RCW没有被GC,并且创建线程退出的时候才会出现,具体的内容因为涉及到.NET 4.0中还没有发布的新功能,这里就不多说了。可以看到,如果采用常规的方法,对于这种在特定的条件下才会重现的问题是很难发现的。

总之,使用WinDbg来设置条件断点,打印相关信息,并且输出到Log文件是一种非常强大的调试方法,可以调试一些非常复杂的Bug,而且具有不需要修改代码的灵活性,可以自由定义自己想需要打印的信息和断点设置的位置,主要的缺点是方法稍显复杂,不过如果适应了之后还是很方便的。我强烈推荐大家在遇到比较复杂的Bug的时候,可以尝试使用一下这种方法,可能具有意想不到的效果哦。

分享到:
评论

相关推荐

    windows调试工具集(windbg)

    8. **调试技巧**:利用Windbg的条件断点(例如"bp module!function if condition"),可以指定在满足特定条件时暂停执行。同时,"log"命令可以记录调试过程中的关键事件,方便后期分析。 9. **插件扩展**:Windbg...

    WinDbg(x86).zip_windbg_断点续传

    传统的单线程断点续传可能无法充分利用现代多核处理器的性能,而WinDbg的多线程支持则可以提高调试效率,允许用户根据需要定制线程数量,以平衡系统资源使用和调试速度。例如,在处理复杂的调试场景时,增加线程数量...

    WinDbg 调试程序崩溃操作详解

    总结,WinDbg是Windows平台上强大的调试利器,尤其在处理程序崩溃、内存泄漏等问题时,能够提供详尽的信息和深度分析。通过熟练掌握WinDbg的使用,开发者可以迅速定位和解决问题,提升软件质量。通过阅读《WinDbg...

    WINDBG调试工具

    描述中的"用windows程序调试,跟踪解决bug的好帮手"进一步强调了WinDbg在调试Windows程序中的作用。通过WinDbg,开发者可以深入到代码层面,追踪程序运行时的细节,包括内存状态、CPU寄存器、调用堆栈等,从而找到并...

    windows超级内核级调试工具WINDBG

    4. **命令行接口**:WinDbg拥有丰富的命令集,用户可以通过输入命令执行各种调试操作,如设置断点、查看内存、跟踪调用堆栈等,提供了高度自定义的调试体验。 5. **图形界面**:除了命令行,WinDbg还提供直观的图形...

    WinDbg内核调试.pdf

    ### WinDbg内核调试详解 #### 一、引言 **WinDbg**作为Microsoft提供的强大调试工具,被广泛应用于Windows NT系列操作系统下的软件开发过程中。本文旨在深入探讨WinDbg的基础操作及其在内核调试中的应用。通过本文...

    Windows 调试程序 (WinDbg)

    **Windows调试程序(WinDbg)** WinDbg是一款强大的调试工具,由Microsoft提供,用于对Windows操作系统进行内核模式和用户模式的调试。这款工具是Windows开发和故障排除过程中的得力助手,尤其在处理崩溃、性能问题或...

    windbg调试工具Win10.zip

    4. **命令行接口**:Windbg提供了一套丰富的命令行工具,用户可以通过输入命令进行复杂的调试操作,如设置断点、查看内存、分析堆栈等。 5. **图形界面**:虽然主要以命令行方式操作,但Windbg也提供了图形界面,...

    windbg 调试器扩展

    Windbg调试器扩展是Windows操作系统下强大的调试工具,主要用于分析和诊断系统级的问题,如内核模式崩溃、内存泄漏和性能问题。它以其丰富的命令集和强大的调试功能而闻名,尤其在驱动程序开发和系统故障排查领域...

    windbg工具和windbg内核调试指南

    Windbg是微软开发的一款强大的调试...总之,Windbg是系统级调试的利器,对于开发者和IT运维人员来说,掌握其使用技巧能够极大地提高问题定位和解决的效率。通过学习相关资源,我们可以更好地理解和应对复杂的系统问题。

    很好用的调试软件WinDbg.rar

    WinDbg是一款强大的调试工具,尤其在Windows操作系统环境中,它被广泛用于系统级调试、内核模式调试以及用户模式应用程序的调试。这款软件由微软公司开发,为开发者和系统管理员提供了一个深入理解程序运行时行为的...

    windbg调试命令大全

    ### Windbg调试命令大全 **Windbg** 是一款在Windows平台上功能强大且高效的用户态与内核态调试工具。相较于Visual Studio这样的集成开发环境,Windbg以其轻量化的设计和广泛的调试能力而闻名,尤其适用于系统层面...

    Windows调试工具入门4 - WinDbg内核调试配置

    7. **日志记录**:在调试过程中,利用WinDbg的“log”命令或“kd> .logopen”命令记录调试过程,有助于后期分析。 8. **断点设置**:通过“bp”命令,可以在特定的代码位置设置断点,以便在程序到达该点时暂停执行...

    windbg调试器,32位和64位

    总的来说,无论是在系统层面还是应用层面,Windbg都是一个不可或缺的调试利器,对于深入理解程序行为和解决复杂问题具有巨大帮助。通过熟练掌握Windbg,IT专业人士能够提升其在软件开发和维护中的问题解决能力。

    WinDBG 源码调试工具

    3. **命令行接口**:WinDbg提供了丰富的命令行接口,允许用户通过输入命令来控制调试过程,进行断点设置、内存查看、堆栈跟踪等操作。 4. **图形界面**:虽然主要依赖命令行,但WinDbg也提供了一个图形用户界面,...

    调试:windbg资料

    WinDbg是微软开发的免费源码级调试工具。Windbg可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。在DotNet方面WinDbg是调试分析SSCLI的最佳工具,同时可以和SOS扩展一起调试分析.net程序。最近一段时间...

    WinDbg与vmware虚拟机调试配置 解决WinDbg与vmware不能连接问题

    本文旨在通过解决WinDbg与VMware虚拟机之间无法正常连接的问题来帮助大家更好地理解如何配置这两个工具进行有效的调试。 #### 背景介绍 通常情况下,开发人员会利用VMware搭建一个虚拟环境,然后在这个环境中安装...

    windbg_amd64.msi VC++调试 QTCreator调试器

    VC++(Visual C++)调试功能通常集成在Visual Studio中,允许开发者通过设置断点、查看变量值、单步执行代码以及分析调用堆栈来查找和修复程序中的错误。然而,对于一些复杂的系统级问题或者需要更底层访问的调试...

    windbg最新版 win10

    Windbg是一款强大的Windows调试工具,由Microsoft开发,用于分析、调试和诊断系统及应用程序的问题。在Windows 10和Visual Studio 2017环境下,Windbg尤其重要,因为它们支持最新的开发技术和平台。这款最新版的...

    windbg调试命令 很详细

    ### Windbg调试命令详解 Windbg是一款功能强大的调试工具,被广泛应用于Windows系统下的软件开发、故障排查等场景。本文将详细介绍Windbg中的一些常用调试命令及其应用场景。 #### 1. 进程管理命令 - **~\*s**:...

Global site tag (gtag.js) - Google Analytics