1、 线程调试
对线程的调试用的最多的可能是thread命令了,查看程序中有多少线程使用Infothreads,进入到某个线程的内部使用thread count,这样就可以进入到count线程的内部。线程调试中用的最多的还有就是bt命令,这个命令主要是查看线程的桟信息,光看桟信息还是差了点什么,那就是使用frame count命令,这个命令可以在桟帧之间移动,如果要查看这个桟的源代码就用到之前我们使用的list。在frame中使用的多的还有up和down命令,可以顺序切换桟的frame。
GDB能够使用进程号或者是线程号动态的将调试器附加到已经运行的进程上,用ps命令来确定系统上现在运行的程序。
对线程下断点、监视点等都和前面的进程一样,没有任何区别,只是如果线程出错,每个线程里面都会有一个拷贝的errno变量记录了线程的错误。
2、perror或strerror查看错误
perror函数接受一个参数,且没有返回值,它输出字符串,后面跟一个冒号和空格。
strerroràchar *strerror(int errno)以errno做为参数,并返回一个描述错误的字符串。
3、 strace命令和ltrace命令
strace实用程序输出程序进行的各个系统调用及其参数和返回值-o logfile输出到文件,或-s N选项截断为N个字符。多线程中使用-o log –ff切换,将单个子进程的strace输出捕获到一个名为log.xxx的文件中,其中xxx是进程ID。
ltrace显示库调用,而不是系统调用。
ldd命令可以查看可执行程序需要的库文件。
4、 调试GUI程序
调试GUI,启动GDB,这次不同之处在于告诉GDB程序在不同中断窗口中执行,而不是GDB在运行的那个窗口,在窗口中运行tty命令确定窗口的ID号,所以(gdb) tty/dev/pts/X,现在该程序的所有键盘输入和屏幕输出都将在执行窗口,这时可以在执行窗口中执行类似一下功能的命令sleep xxxx,其中xxxx是睡眠,不接收输入。这样在该窗口中的键盘输入会进入程序,而不是shell命令窗口。
或者使用另一种方法,让程序先执行,打开另一个窗口运行gdb,然后附加上这个运行的程序。
5、 调试助跑
5.1 splint的使用
使用splint对程序静态检查,可以对程序包括返回值在内的检查,使用之前先进行安装,debian系统用apt-get install,如果不记得程序的名称,可以使用apt-cache search搜索后再安装。如果是红帽系列应该使用yum命令查找并安装。该程序提供了几种不同的检查功能,严格控制程度不同分别有standard默认选项,checks是中度检查,strict是高度严格检查。如果使用某个功能使用+,不使用某个功能使用-。例如splint
+weak *.c。
put.c
#include <stdio.h> int main(void) { int i; scanf("%d", &i); return 0; }
使用splint检测,默认的话会提示你scanf有返回值,你没有接收,如果使用+weak之后就不会提醒。
5.2 ElectricFence的使用
该软件所提供的功能是内存方面的检查,可以是越界,重复释放,访问错误,内存泄漏等。内存越界检查在gcc中也提供了这个功能,只是gcc中是以宏的形式表现出来的。编写程序的时候有时会把访问数组的个数弄错,导致越界访问,越界访问并不一定表现出任何错误。这也是最可怕的,所以使用该软件联合编译会检查你的程序,数组有没有越界,如果越界,编译执行会出现段错误并打印出错误的地方。例如:gcc –g3 –Wall –std=c99 outofband.c
–o outofband –lefence,efence默认只捕获越出动态分配区域最右一个元素的读或写。
outofbound.c
#include <string.h> #include <stdio.h> #include <stdlib.h> int main(void) { int *a = (int *)malloc(2 * sizeof(int)); for (int i = 0; i <= 2; i++) { a[i] = i; printf("%d\n", a[i]); } free(a); return 0; }
6、VIM使用技巧
k查询man页中的函数,在程序中直接使用k查看。
gd和gD查找变量声明。
[^D和]^D跳到宏定义。
]d,[d,[D,]D显示宏定义。
总结
《调试软件艺术》的读书笔记到此也就完成了,希望大家能够从中得到你想知道的调试技巧。如果有任何错误,希望大家指正。谢谢