或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你在 UNIX 平台下做开发,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。那么如果我想在Windows下使用GDB调试程序,应该怎么做呢?
一、什么是GDB?
「GNU调试器」(英语:GNU Debugger,缩写:「GDB」),GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。
二、它有哪些特点?
GDB具备各种调试功效,能针对计算机程序的执行进行追踪与警告,使用GDB的调试人员可以监督及修改程序的内部变量值,甚至监督与修改独立于主程序运作外,以独立个体类型调用(调用使用)的函数。
下面讲人话,它可以做以下事情:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。
三、前置条件
为了能用gdb调试程序,得先用gcc编译,gcc和gdb在Windows上是没有预装的,所以为了能用上它们,我们得先在 Windows 上安装好【MinGW】这个软件。
mingw(Minimalistic GNU for Windows) 编译器系统,建立在GCC和binutils项目上。MinGW提供了一套简单方便的Windows下的基于GCC程序开发环境,是一套GNU工具集合(一系列免费的Windows使用的头文件和库文件,同时整合了GNU工具集,特别是GNU程序开发工具,如经典gcc,g++,make等)。该集合允许人们在没有第三方动态链接库的情况下使用GCC产生Windows32程序。它在windows平台模拟了Linux下的GCC开发环境,为C++的跨平台提供了良好的基础支持。
1、下载安装
废话不多说,我们先访问MinGW 的主页:https://mingw.osdn.io/
MinGW 的主页
下载安装MinGW :https://osdn.net/projects/mingw/downloads/68260/mingw-get-setup.exe/
安装MinGW
安装包就是这个
安装包
安装很简单的,就不多说了,注意记住安装的目录,如 D:\Tools\MinGw,下面修改环境变量时还会用到
准备安装
安装好打开就是这个样子,大家感兴趣可以试试
程序打开后
2、简单配置一下
我们在里面找到【mingw32-gcc.bin】, 【mingw32-gcc-g++.bin】, 【mingw32-gdb.bin】,以及【mingw32-gdb.bin】 第一个是c语言文件的编译器,第二个是c++的,第三个是用来调试编译后文件的,最后一个就是gdb调试用到的。(注意class属性要为bin)
安装编译器
右键点击Mark for Installation(没截到图)
然后点击左上角的Installation
菜单中的Apply changes
选项,然后管理器将开始在线安装或更新被选中的组件
在线安装
不要犹豫和搞其他操作,直接点击Apply申请
点击Apply申请
安装中…
下面耐心等待程序的安装就好,安装完成后关闭包管理器。如果由于某种原因安装未能成功,在退出程序前程序将给予提示,选择【review changes】选项重新安装即可。
3、修改环境变量
安装好之后,是不能直接使用的,还需添加到环境变量。
选择计算机—属性—高级系统设置—环境变量,在系统变量中找到 Path 变量,在后面加入 min-gw的安装目录,如 D:\Tools\MinGw
修改环境变量
我们 win+r 打开运行,输入cmd,再输入 gcc -v 验证一下是否安装成功,g++也可以
打开gcc验证一下
打开gdb验证一下
就很简单,对吧。
四、GDB相关命令及程序演示
先上一段演示代码,新建一个名为mmap.c的C文件
#include <stdio.h>
int sum(int n) {
int sum = 10;
for (int i = 0; i <= n; i++) {
sum += i;
printf("1:the sum of 1-%d is %d\n", i, sum);
}
return sum;
}
int main() {
int n = 0;
sum(50);
for (int i = 0; i <= 50; i++) {
n += i;
}
printf("2:the sum of 1-50 is %d\n", sum);
return0;
}//演示代码略简单,大家轻喷
启动gdb后,进入到交互模式,通过以下命令完成对程序的调试。注意高频使用的命令一般都会有缩写,熟练使用这些缩写命令能提高调试的效率。
进入代码所在目录,在目录内启动命令调试符,输入以下代码:
gcc -gstabs -o mmap mmap.c
源文件gcc编译一下
注意必须使用 -gstabs 参数,编译会加入调试信息,否则无法调试执行文件
编译后获得mmap.exe
输入【gdb mmap】 进入gdb调试,mmap为文件名
gdb mmap //选择我们之前编译的文件,进入gdb调试
(gdb)list 1 //将显示当前文件以“行号”为中心的前后10行代码,list 10
进入gdb调试
(gdb)breakpoint 6 //简写成b 6,既在第六行设置断点
(gdb)info b //显示当前程序的断点设置情况
扩展:
b fn1 if a>b //条件断点设置
break func //在函数func()的入口处设置断点,如:break cb_button
delete 断点号n //删除第n个断点
disable 断点号n //暂停第n个断点
enable 断点号n //开启第n个断点
clear 行号n //清除第n行的断点
设置断点并查看
(gdb)r //run:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令
(gdb)n //next:简记为n,执行下一行语句(单步调试)
(gdb)bt //显示当前运行的堆栈列表
(gdb)show args //查看设置好的参数
(gdb)info frame //显示当前堆栈页的所有变量
运行程序并查看堆栈列表
单步调试
显示当前堆栈页的所有变量
(gdb)info registers //查看所有寄存器
(gdb)info function //查询函数
(gdb)x/4x $esp //查看4个字节的栈顶寄存器的内容
(gdb)x/4x $ebp //查看4个字节的栈底寄存器的内容
扩展知识
(r是64位,e是32位)
//eax 累加寄存器,它是很多加法乘法指令的缺省寄存器
//ebx 基地址寄存器, 在内存寻址时存放基地址
//esi 来源索引暂存器 edi 目的索引暂存器
//esp 栈顶寄存器 ebp 栈底寄存器
//eflags 状态位寄存器
//ss 堆栈段寄存器
//cs 代码段寄存器
//ds 数据段寄存器
查看所有寄存器
查看4个字节的栈顶(栈底)寄存器的内容
查看其他寄存器
(gdb)quit //简记为q,退出gdb
ps:交互模式下直接回车的作用是重复上一指令,对于单步调试非常方便;
ps:在Linux中,栈顶寄存器和栈底寄存器的内容是无法读出来的,会显示权限不够
退出gdb调试
五、写在最后
最近刚接触到gdb方面的知识,文章写的有些粗糙,师傅们轻喷。