#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;
}
先启动我们的程序,打开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文件拷贝过去,就可以现场进行调试了。



