很多学弟学妹向我们cpp学导询问课程习题如何解决。但是做题并不算学好了cpp,上机多练习永远是cpp的制胜绝招。
所以本篇专门介绍c&cpp中的调试技巧,帮助学弟学妹们进行上机的练习,并且为日后进行实际的开发养成好习惯。
本篇教程仍然分为两篇,Based篇中主要从代码角度进行;Advanced篇主要从linux操作系统gdb调试器的角度进行。
Ps: 上次有学弟学妹问linux是什么,吹泡泡学导笑而不语。既然有了好奇心,那就去图书馆查查吧。5楼有很多相关的书籍 :-)
Based
1 预处理器调试标记以及运行时调试标记
调试过程中,通过无数的printf打印函数或者 cout输出流 调试信息debug程序执行状态,在进行代码发布的时候又常常需要把这些调试信息去掉,可能以后工作中可能需要重新增加这些调试信息,如此大大增加了时间成本。
首先加入预处理文件 debug.h
debug.h
#ifndef __DEVICE1_H
#define __DEVICE1_H
#define DEBUG
#endif
在主要函数中加入你的打印信息,如此便可以进行调试信息的输出.
main.c
#include
#include "debug.h"
int main()
{
using namespace std;
#ifdef DEBUG
cout << "Debug info" << endl;
#endif
return 0;
}
关闭调试信息只需要添加语句 #undef DEBUG
main,c
#include
#include "debug.h"
#undef DEBUG
using namespace std;
int main()
{
#ifdef DEBUG
cout << "Debug info" << endl;
#endif
return 0;
}
2 使用你的assert宏函数进行断言
assert() 宏函数中,,当使用assert时候,给他个参数,即一个判读为真的表达式。预处理器产生测试该断言的代码,如果断言不为真,则发出一个错误信息告诉断言是什么以及它失败一会,程序会终止。
code
#include< assert.h>
using namsapce std;
int main() {
int i=100;
#ifdef DEBUG
assert(i!=100); //Fails
#endif
return 0;
}
Advanced
本篇主要是关于gdb的命令行调试方法
启动GDB的方法有以下几种:
1、gdb
program也就是你的执行文件,一般在当然目录下。
2、gdb core
用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。
3、gdb
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上
Ps:gdb 其中目录或环境变量下必须有.c文件,否则找不到源码
(gdb) lP
16 demo.c: No such file or directory.
二、设置观察点(WatchPoint)
观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点:
watch
为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。
rwatch
当表达式(变量)expr被读时,停住程序。
awatch
当表达式(变量)的值被读或被写时,停住程序。
info watchpoints
列出当前所设置了的所有观察点。
watch p 是查看 *(&p), 是p 变量本身。
watch (*p) 是 p 所指的内存的内容, 查看地址,一般是我们所需要的。
我们就是要看莫地址上的数据是怎样变化的,虽然这个地址具体位置只有编译器知道。
c. watch 一个数组或内存区间
char buf[128], watch buf,
是对buf 的128个数据进行了监视. 此时不是采用硬件断点,而是软中断实现的。
软中断方式去检查内存变量是比较耗费cpu资源的。
在使用watch时步骤如下:
1. 使用break在要观察的变量所在处设置断点;
2. 使用run执行,直到断点;
3. 使用watch设置观察点;
4. 使用continue观察设置的观察点是否有变化。
demo
(gdb) b 16
Breakpoint 7 at 0x804841a: file demo.c, line 16.
(gdb) c
Continuing.
Breakpoint 7, add_range (low=1, high=46) at demo.c:16
16 int i, sum=0;
(gdb) watch i
Hardware watchpoint 8: i
(gdb) c
Continuing.
Hardware watchpoint 8: i
Old value = 0
New value = 1
0x08048427 in add_range (low=1, high=46) at demo.c:17
17 for (i = low; i <= high; i++)
三、设置捕捉点(CatchPoint)
你可设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常。设置捕捉点的格式为:
catch
当event发生时,停住程序。event可以是下面的内容:
1、throw 一个C++抛出的异常。(throw为关键字)
2、catch 一个C++捕捉到的异常。(catch为关键字)
3、exec 调用系统调用exec时。(exec为关键字,目前此功能只在HP-UX下有用)
4、fork 调用系统调用fork时。(fork为关键字,目前此功能只在HP-UX下有用)
5、vfork 调用系统调用vfork时。(vfork为关键字,目前此功能只在HP-UX下有用)
6、load 或 load 载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用)
7、unload 或 unload 卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用)
tcatch
只设置一次捕捉点,当程序停住以后,应点被自动删除。
南京理工大学本科生学业指导中心
微信公众号 : 导学小纸条
地址:逸夫楼201
作者、编辑:吴睿喆