CGDB 是GDB的前端,在终端窗口中意图形化的形式来调试代码(基于ncurse),非常方便。相对于GDB来说,可以很大的提高效率。,这篇文章就来分享一下CGDB的最基本使用方法,如果是第一次听说,强烈建议您体验一下,一定会爱上它的!,在编译之前,先看一下代码,你能发现其中的bug吗?,当然了,在编译的时候,编译器以Warning的方式给出了风险提示。因为示例代码很简单,所以很容易发现。,但是在一个项目中,如果不喜欢消除编译Warning警告的话,这个bug还是比较隐蔽的。,编译测试代码:gcc -g test.c -o test,因为要使用GDB调试,所以别忘了加上-g选项。,发现user_data.flag的值不对,决定在调用get_data之前的那行下一个断点,然后从头开始执行:,查看代码行号:,下断点在25行:,开始运行:,在断点处停了下来,此时该赋值语句还没有执行,所以先单步执行一次:,此时,打印一下这个变量user_data.flag的值和地址:,因为待会进入被调用函数,这个变量就不可见了,所以需要通过地址来打印。,此时赋值是正确的,再接着往下执行,进入被调用函数get_data()了,,这个函数一共就4行代码,我们每单步执行一句,就打印一下user_data.flag变量的内容。,单步执行下一行memcpy处,并且看一下user_data.flag变量地址处的内容是否仍然为:0xa5:,继续单步执行(因为不需要跟进memcpy、strlen的内部,所以使用next命令),并打印:,发现问题了:在执行*len = strlen(g_data)语句之后,变量user_data.flag地址中的内容就被改变了。,再仔细检查一下代码,就可以诊断出是数据类型使用错了。,解决bug: get_data()函数的最后一个参数,应该是unsigned short型指针才正确。,问题是解决了,但是回过头来看一下gdb的调试过程,还是比较繁琐的:调试指令和代码显示夹杂在一起,需要敲很多指令。,启动CGDB之后,终端窗口被评分为上下两部分:上面是代码窗口,下面是调试窗口。,
,按下ESC键进入代码窗口,此时可以上下浏览代码,并且可以进行一系列的操作:,还有很多方便的快捷键:,按下i键回到调试窗口,进入调试模式,使用的调试指令与GDB几乎一样!,也就是说:可以在实时查看代码的情况下进行调试操作,大大提高了效率。,我们按照上面GDB的调试过程走一遍:,按下ESC键进入代码窗口,此时代码前面的行号如果是白色的,表示所在的当前行。,按下j键,向下移动高亮的当前行。当移动到25行时,如下:,
,按下空格键,表示在此行设置一个断点,此时行号变成红色的:,
,并且在调试窗口打印一行信息:,按下i键回到调试操作窗口,然后输入运行指令r,会在第25行停下来的,如下绿色的箭头所示:,
,当然了,调试窗口也会打印出相关信息:,单步step执行这条赋值语句,然后打印一下user_data.flag的值和地址:,此时,赋值语句正确执行,打印的值也是符合预期的。,再执行单步指令,进入函数get_data()内部:,此时,上面的代码窗口自动进入get_data()相关的代码,如下所示:,
,继续单步,在执行赋值语句*len = strlen(g_data);之前打印一下变量user_data.flag地址中的内容:,正确!然后执行赋值语句之后,再次打印:,发现问题:在执行*len = strlen(g_data)语句之后,变量user_data.flag地址中的内容就被改变了。,CGDB的操作过程,虽然我写的比较啰嗦,但是实际使用起来,真的是非常的丝滑,就像巧克力一样!
© 版权声明
文章版权归作者所有,未经允许请勿转载。