• 使用WinDbg进行动态调试


    前言

    • 本文章主要介绍如何使用WinDbg进行动态调试。如果程序崩溃后,没有记录dump文件,或者程序启动时发生异常,比如常见的 应用程序无法正常启动(0xc000007b) 报错,都可以使用WinDbg动态调试功能来定位问题。文章最后,对WinDbg常用命令进行了总结。
    • 对WinDbg不熟悉的可以参考我的另一篇WinDbg入门教程 WinDgb安装和使用

    什么时候使用WinDbg进行动态调试

    • 程序崩溃后没有生成dump文件
    • 使用visual studio调试时发生异常,看不到完整的调用堆栈
    • 程序启动时发生异常错误,比如比较常见的 应用程序无法正常启动(0xc000007b)

    WinDbg动态调试步骤

    • 测试程序
      •   #include 
          #include 
          
          void myfunc() {
          	printf("join to myfunc...\n");
          
          	//这里程序会崩溃
          	char* p = NULL;
          	memcpy(p, "hello word", strlen("hello word"));
          
          	printf("end myfunc");
          }
          
          void myMath(int a, int b) {
          	int sum = 0;
          	sum = a + b;
          	printf("sum = %d\n", sum);
          
          	myfunc();
          
          	int minus = 0;
          	minus = a - b;
          	printf("sum = %d\n", sum);
          }
          
          int main() {
          
          	myMath(10, 20);
          	system("pause");
          	return 0;
          }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
    • 使用WinDbg动态调试程序
      • 先启动我们的程序,打开WinDbg,选择File->Attach to a Process,然后选择要调试的目标进程。这里会看到当前运行的所有进程,选择你要调试的进程即可。
        在这里插入图片描述

      • 如果要调试程序无法正常启动,或者说启动后会直接退出,那么也可以直接使用WinDbg打开程序进行调试,选择 File->Open Executable,选择要调试的程序打开即可。

      • 运行后默认会终端,在命令行输入g命令,可以继续运行
        在这里插入图片描述
        在这里插入图片描述

      • 通过上面测试程序可以知道,程序运行后会崩溃,从调试信息可以看到,发生Access violation,即内存访问违规。

      • 使用kn命令,可以看到具体的堆栈信息,并且打印了的行号。
        在这里插入图片描述

      • 如果这里的堆栈没有函数和行号信息,是因为没有加载pdb文件,选择File->Symbol File Path将pdb所在目录添加进去即可。

      • 使用lm命令可以查看pdb文件是否加载上了,使用lm vm 模块名可以看到更详细的信息。如果pdb文件的完整路径打印出来了,说明加载成功了。
        在这里插入图片描述
        在这里插入图片描述

      • 如果pdb文件加载失败,第一个原因就是可执行程序和pdb文件不一致,也就是说可执行程序可能改过代码了,但pdb文件还是之前的。还有一个原因就是可执行程序和pdb文件时间戳不一致,也就是说代码是一致的,但可执行程序生成时间和pdb生成时间不一致。如果还有其他问题导致pdb文件加载失败,可以使用 .reload /f 可执行程序名 强制加载pdb文件。

      • 可以通过 File->Source File Path将源代码路径设置进行,就可以在WinDbg中使用源代码调试了
        在这里插入图片描述

      • 那么相比于使用Visual Studio调试,WinDbg有什么好处呢。比如我们写完程序,放到客户电脑上,程序运行异常了,从日志和dump文件都分析不出问题,而且开发机还复现不了问题。这个时候就只能在客户电脑上调试了。那如果使用Visual Studio调试,我们不仅要去搭建环境,而且还要将代码拷贝到客户电脑上,实际场景肯定是不现实的。这个时候就可以使用WinDbg来进行调试了,只需要在客户电脑上安装一个WinDbg,并把对应程序的pdb文件拷贝过去,就可以现场进行调试了。

    通过WinDbg导出dump文件

    • 如果程序崩溃了,但我们程序又没有记录dump文件的功能,可以通过 .dump /ma dump文件名 命令将dump文件导出,事后进行分析。
      在这里插入图片描述

    应用程序无法正常启动(0xc000007b)分析

    • 这种报错一般是由于可执行程序的依赖库位数不匹配导致的,比如我这个可执行程序依赖的vcruntime140d.dll是64位,我打包发布的时候,拷了一个32位的库进去,运行时就会报这个错误。
      在这里插入图片描述
      在这里插入图片描述
    • 那实际项目中,可执行程序依赖的库是很多的,我们不知道哪一个依赖库出现了问题,就可以使用WinDbg来进行动态调试。
      在这里插入图片描述
    • 使用WinDbg调试时可以看到,加载vcruntime140d.dll时出现了错误,这样我们就能准确定位到是哪个依赖库出问题了。

    WinDbg常用命令

    • g
      • 跳过当前中断,继续运行
    • .ecxr
      • 切换到发生异常的线程中。如果是动态调试,会直接切换到异常的线程中,因此不需要执行此命令。
    • kn/kv/kp
      • 查看当前线程的函数调用堆栈
    • lm
      • 查看二exe或者二进制文件的信息,lm vm fileDump 可以查看fileDump模块的详细信息。
    • .reload
      • 加载pdb文件,比如 .reload /f fileDump.exe , 强制加载 fileDump.exe的pdb文件
    • ~
      • 查看当前进程所有线程信息
    • ~ns
      • 切换到n号线程中
    • !analyze
      • 详细分析当前异常,完整命令为 !analyze -v
    • .dump
      • 导出dump文件,比如 .dump /ma F:\0001.dmp
    • bp/bl/bc
      • bp : 添加断点,比如 bp fileDump!main,给fileDump模块中的main函数设置断点
      • bl : 列出当前所有断点
      • bc : 清除断点
    • r
      • 查看当前线程所有寄存器的值
    • .cls
      • 清屏
    • .effmach
      • 切换当前进程的上下文
  • 相关阅读:
    JavaScript:从入门到进阶的旅程
    nodejs+vue+elementui在线考试系统express vscode
    外汇天眼:ADSS已与analytics KX供应商就合作达成一致
    Python strftime 与 strptime
    SpringCloud:注册中心nacos(集群部署)
    云边端协同场景下的“AI+”视频融合能力,如何赋能多行业应用?
    【python游戏制作】僵尸来袭 ~ 快来一起创造植物叭~
    教育部:每所学校贷款项目总投资原则上不低于2000万
    hadoop3.x入门到精通-阶段六(深入Hadoop源码达到定制化阶段)
    java毕业设计成品基于JSP+SSH框架的城市公交查询系统[包运行成功]
  • 原文地址:https://blog.csdn.net/new9232/article/details/132774219