所有信息参考官方文档:开始使用 WinDbg(用户模式) - Windows drivers | Microsoft Learn
需要着重关注的标签页如下:
用户模式(入门)
命令摘要
Help菜单上的命令Contents- .sympath(设置符号路径)
- .reload(重新加载模块)
- x(检查符号)
- g(转到)
Debug菜单上的命令Break- lm(列出已加载的模块)
- k(显示堆栈回溯)
- bu(设置断点)
- bl(断点列表)
- ~(线程状态)
- ~s(设置当前线程)
- .sympath+(设置符号路径)附加到现有符号路径
- srcpath(设置源路径)
Debug菜单上的命令Step Into(F11)- !analyze -v
- qd(退出和分离)
内核模式(入门)
命令摘要
- “帮助”菜单上的“内容”命令
- .sympath(设置符号路径)
- .reload(重新加载模块)
- x(检查符号)
- g(转到)
- dt(显示类型)
- 在“调试”菜单上“中断”命令
- lm(列出已加载的模块)
- k(显示堆栈回溯)
- bu(设置断点)
- bl(断点列表)
- bc(断点清除)
- “调试”菜单上的“单步调试”命令 (F11)
- dt nt!_FILE_OBJECT 检查数据类型,如图:

调试方法
标准
- 使用断点
- 读取和写入内存
- 使用 !analyze 扩展
- 在启用驱动程序验证程序的情况下处理 Bug 检查
- 非侵入式调试(用户模式)
- 在程序集模式下调试
- 在源模式下调试
- 调试优化的代码和内联函数
- 使用 Windows 调试器调试托管代码
- 使用 Windows 调试器调试 Windows 应用
- 更改上下文
- 控制进程和线程
- 使用调试器标记语言
- 控制异常和事件
- 查找进程 ID
- 调试堆栈溢出
- 手动遍历堆栈
- 调试包含 JScript 帧的堆栈跟踪
- 调试应用程序错误
- 重新附加到目标应用程序
- 使目标计算机崩溃和重新启动目标计算机
- 与目标计算机同步
- 查找内存泄漏
- 调试超时
- 调试已停止的系统
- 调试多个目标
- 跟踪占用大量处理器资源的进程
- 确定对象的 ACL
- 显示关键节
- 调试死锁
- 调试失败的驱动程序卸载
- 读取 Bug 检查回调数据
- 使用 KD 调试用户模式故障
- 映射驱动程序文件
- 来自目标的消息
专业
- 调试 Arm64
- Windows 运行时调试
- 内核模式驱动程序框架调试
- 用户模式驱动程序框架调试
- 调试托管代码
- 调试设备节点和设备堆栈
- 调试即插即用和电源问题
- 使用 KD 调试用户模式故障
- 调试设备安装包中的辅助安装程序
- 调试双重引导计算机
- 调试 Windows 安装程序和 OS 加载程序
- 调试 CSRSS
- 调试 WinLogon
- 调试 BIOS 代码
- 指定模块和函数所有者
调试死锁
1. 启动调试会话
首先,确保你以调试模式启动应用程序,可以使用以下命令:
windbg -p <ProcessID> 或windbg <path-to-your-executable>
2. 捕获死锁
当你怀疑程序已经发生死锁时,可以使用以下步骤捕获当前线程的状态:
- 查看当前线程:使用
!thread命令查看当前线程的状态。!thread - 查看线程信息:查找所有线程,特别是那些处于等待状态的线程。
!process 0 0 - 查看堆栈信息:对于所有线程,使用
!stack命令查看其调用堆栈信息,了解它们正在等待的资源。!stack
3. 分析锁定和等待状态
- 查看资源和锁定:使用
!locks命令查看当前的锁定状态,找出哪些线程在等待哪些锁!locks - 查看等待链:使用
!wait命令查看当前等待链,识别是否存在死锁。!wait
4. 分析线程和堆栈
- 识别死锁:查找具有相互依赖关系的线程。例如,线程 A 等待线程 B 持有的锁,而线程 B 又在等待线程 A 持有的锁。
- 查看线程优先级和状态:使用
!thread <ThreadID>来查看特定线程的详细信息,包括其优先级和状态。
5. 查看事件和信号量
如果你使用的是事件或信号量,可以使用以下命令检查它们的状态:!evnt !semaphore
6. 记录日志
在调试过程中,记录下观察到的死锁条件和状态信息,这对于后续分析和修复问题很有帮助。
7. 示例命令
以下是一些可能有用的命令示例:!analyze -v // 进行自动分析 !threads // 查看所有线程 !locks // 查看锁定情况 !process 0 0 // 查看所有进程和线程 !wait // 查看当前等待链
8. 解决死锁
- 代码审查:检查代码中涉及锁定和共享资源的部分,确保没有循环依赖。
- 设计更改:考虑使用超时机制、避免嵌套锁或改变资源请求的顺序来减少死锁的可能性。
总结
通过上述步骤,你可以在 WinDbg 中有效地分析和调试死锁问题。死锁的诊断需要细致的分析和对线程状态的理解,通过调试命令的配合使用,可以找到问题的根源并进行修复。
调试内存泄漏
使用 WinDbg 调试内存泄漏可以通过多种方法进行,以下是一些常用的步骤和命令,帮助你定位和解决内存泄漏问题。
1. 启动调试会话
首先,确保你的应用程序在调试模式下运行,可以使用以下命令启动 WinDbg:windbg -p <ProcessID> 或者,如果你想要启动应用程序并立即进行调试:windbg <path-to-your-executable>
2. 加载扩展
在 WinDbg 中,有一些扩展可以帮助你更好地分析内存使用情况。加载 !heap 扩展可以帮助你检查堆的状态:.loadby sos clr // 对于 .NET 应用 !heap -s // 概览当前堆的使用情况
3. 检查内存分配
- 查看分配的内存:使用以下命令查看堆中所有分配的内存块:
!heap -stat // 统计堆的内存分配 !heap -p -a <Address> // 查看特定地址的堆信息 - 查看内存分配跟踪:使用
!heap -flt命令来查看特定大小的内存分配,可以帮助识别大块内存的使用情况。!heap -flt s <Size> // 查看特定大小的分配
4. 内存泄漏检测
- 启用内存跟踪:对于某些情况下,你可以启用内存跟踪:
!heap -p -a <Address> // 监控特定的地址 - 查看泄漏的内存:在程序结束时,使用
!heap -s命令查看任何未释放的内存块:!heap -s // 显示堆的状态,包括潜在的泄漏
5. 使用 !analyze 命令
使用 !analyze -v 命令进行详细分析,这可以帮助发现与内存相关的问题:!analyze -v
6. 查看分配栈
使用 !heap -p -a <Address> 命令查看特定内存分配的调用堆栈,找出哪个函数分配了该内存:!heap -p -a <Address> // 查看该地址的分配调用栈
7. 记录和比较
- 记录分配情况:在应用程序的不同运行阶段记录分配情况,以比较和找出内存的增加。
- 使用工具:考虑结合其他工具(如 Visual Studio 的内存分析器或其他专用的内存泄漏检测工具)进行更深入的分析。
8. 总结和解决
一旦识别出泄漏的内存块,回到源代码进行审查,找出未正确释放内存的地方,并进行修复。
示例命令
!heap -s // 显示堆的总体情况 !heap -stat // 堆的统计信息 !heap -p -a <Address> // 查看特定地址的堆信息 !analyze -v // 进行详细分析
总结
通过这些步骤,你可以在 WinDbg 中有效地分析和调试内存泄漏问题。定期使用这些工具和命令可以帮助你保持代码的内存健康,避免潜在的内存问题。
2万+

被折叠的 条评论
为什么被折叠?



