在后台开发中,strace -p 能够很方便的查看系统调用的参数,返回值,耗时等信息。
gdb -p pid //调试pid进程
能够调试pid对应的程序
在gdb中用set print element 0,然后p 变量,可以查看到变量的全部信息,不会被截断(默认只会输出一部分)
lsof -p pid //查看进程pid打开的文件描述符,(一般情况下,一个进程可以打开的文件描述符的个数不超过1024)
防止文件描述符泄露,内存泄露不仅仅是堆内存泄露,还有句柄泄漏。
df -l 和du -sh 统计到的文件大小不同,可能是因为文件目录项被删除了,但是文件还被打开着,inode还被占用着。
ps -eLf //查看操作系统中的线程信息,ps -elf 只能看到进程信息。
GDB 命令行参数
启动 GDB:
l gdb executable
l gdb -e executable -c core-file
l gdb executable -pid process-id
(使用命令 'ps -auxw' 可以查看进程的 pid)
选项 |
含义 |
–help |
列出命令行参数。 |
–exec= file |
指定可执行文件。 |
–core= core-file |
指明 core 文件。 |
–command= file |
从指定文件中读取 gdb 命令。 |
–directory= directory |
把指定目录加入到源文件搜索路径中。 |
–cd= directory |
以指定目录作为当前路径来运行 gdb 。 |
–nx |
不要执行 .gdbinit 文件中的命令。默认情况下,这个文件中的命令会在所有命令行参数处理完后被执行。 |
–batch |
在非交互模式下运行 gdb 。从文件中读取命令,所以需要 -x 选项。 |
–symbols= file |
从指定文件中读取符号表。 |
-write |
允许对可执行文件和 core 文件进行写操作。 |
–quiet |
不要打印介绍和版权信息。 |
–tty= device |
指定 device 为运行程序的标准输入输出。 |
–pid= process-id |
指定要附属的进程 ID 。 |
GDB命令
GDB 中使用的命令:
命令 |
描述 |
help |
列出 gdb 帮助信息。 |
help topic |
列出相关话题中的 gdb 命令。 |
help command |
列出命令描述信息。 |
apropos search-word |
搜索相关的话题。 |
info args |
列出运行程序的命令行参数。 |
info breakpoints |
列出断点。 |
info break |
列出断点号。 |
info break breakpoint-number |
列出指定断点的信息。 |
info watchpoints |
列出观察点。 |
info registers |
列出使用的寄存器。 |
info threads |
列出当前的线程。 |
info set |
列出可以设置的选项。 |
Break and Watch |
|
break funtion |
在指定的函数,或者行号处设置断点。 |
break + offset |
在当前停留的地方前面或后面的几行处设置断点。 |
break file:func |
在指定的 file 文件中的 func 处设置断点。 |
break file:nth |
在指定的 file 文件中的第 nth 行设置断点。 |
break * address |
在指定的地址处设置断点。一般在没有源代码时使用。 |
break line-number if condition |
如果条件满足,在指定位置设置断点。 |
break line thread thread-number |
在指定的线程中中断。使用info threads可以显示线程号。 |
tbreak |
设置临时的断点。中断一次后断点会被删除。 |
watch condition |
当条件满足时设置观察点。 |
clear |
清除函数 func 处的断点。 |
delete |
删除所有的断点或观察点。 |
delete breakpoint-number |
删除指定的断点,观察点。 |
disable breakpoint-number-or-range |
不删除断点,仅仅把它设置为无效,或有效。 |
enable once breakpoint-number |
设置指定断点有效,当到达断点时置为无效。 |
enable del breakpoint-number |
设置指定断点有效,当到达断点时删除它。 |
finish |
继续执行到函数结束。 |
Line Execution |
|
step |
进入下一行代码的执行,会进入函数内部。 |
next |
执行下一行代码。但不会进入函数内部。 |
until until line-number if condition |
继续运行直到到达指定行号,或者函数,地址等。 |
return |
弹出选中的栈帧(stack frame)。如果后面指定参数,则返回表达式的值。 |
stepi |
执行下一条汇编/CPU指令。 |
info signals |
当收到信号时执行下列动作:nostop(不要停止程序),stop(停止程序执行),print(显示信号),noprint(不显示),pass/noignore(允许程序处理信号),nopass/ignore(不让程序接受信号) |
where |
显示当前的行号和所处的函数。 |
Program Stack |
|
backtrace |
显示当前堆栈的追踪,当前所在的函数。 |
backtrace full |
打印所有局部变量的值。 |
frame number |
选择指定的栈帧。 |
up number |
向上或向下移动指定个数的栈帧。 |
info frame addr |
描述选中的栈帧。 |
info args |
显示选中栈帧的参数,局部变量,异常处理函数。 all-reg 也会列出浮点寄存器。 |
Source Code |
|
list |
列出相应的源代码。 |
set listsize count |
设置 list 命令打印源代码时的行数。 |
directory directory-name |
在源代码路径前添加指定的目录。 |
directory |
当后面没有参数时,清除源代码目录。 |
Examine Variables |
|
print variable |
打印指定变量的值。 |
p * array-var @ length |
打印 arrary-var 中的前 length 项。 |
p/x var |
以十六进制打印整数变量 var 。 |
p/d var |
把变量 var 当作有符号整数打印。 |
p/u var |
把变量 var 作为无符号整数打印。 |
p/o var |
把变量 var 作为八进制数打印。 |
p/t var |
以整数二进制的形式打印 var 变量的值。 |
p/c variable |
当字符打印。 |
p/f variable |
以浮点数格式打印变量 var 。 |
p/a variable |
打印十六进制形式的地址。 |
x/w address |
打印指定的地址,以四字节一组的方式。 |
call expression |
类似于 print ,但不打印 void 。 |
disassem addr |
对指定地址中的指令进行反汇编。 |
Controlling GDB |
|
set gdb-option value |
设置 GDB 的选项。 |
set print array on |
以可读形式打印数组。默认是 off 。 |
set print array-indexes on |
打印数组元素的下标。默认是 off 。 |
set print pretty on |
格式化打印 C 结构体的输出。 |
set print union on |
打印 C 中的联合体。默认是 on 。 |
set print demangle on |
控制 C++ 中名字的打印。默认是 on 。 |
Working Files |
|
info files |
列出当前的文件,共享库。 |
file file |
把 file 当作调试的程序。如果没指定参数,丢弃。 |
core file |
把 file 当作 core 文件。如果没指定参数,则丢弃。 |
exec file |
把 file 当作执行程序。如果没指定参数,则丢弃。 |
symbol file |
从 file 中读取符号表。如果没指定参数,则丢弃。 |
load file |
动态链入 file 文件,并读取它的符号表。 |
path directory |
把目录 directory 加入到搜索可执行文件和符号文件的路径中。 |
Start and Stop |
|
run |
从头开始执行程序,也允许进行重定向。 |
continue |
继续执行直到下一个断点或观察点。 |
continue number |
继续执行,但会忽略当前的断点 number 次。当断点在循环中时非常有用。 |
kill |
停止程序执行。 |
quit |
退出 GDB 调试器。 |
GDB 操作提示
l 在编译可执行文件时需要给 gcc 加上 "-g" 选项,这样它才会为生成的可执行文件加入额外的调试信息。
l 不要使用编译器的优化选项,比如: "-O","-O2"。因为编译器会为了优化而改变程序流程,那样不利于调试。
l 在 GDB 中执行 shell 命令可以使用:shell command
l GDB 命令可以使用 TAB 键来补全。按两次 TAB 键可以看到所有可能的匹配。
l GDB 命令缩写:例如 info bre 中的 bre 相当于 breakpoints。
GDB 在 Emacs 中的操作:
emacs 按键 |
动作 |
M-x gdb |
切换到 gdb 模式。 |
C-h m |
显示 gdb 模式介绍信息。 |
M-s |
等同于gdb 中的 step 命令。 |
M-n |
等同于gdb 中的 next 命令。 |
M-i |
等同于gdb 中的 stepi 命令。 |
C-c C-f |
等同于gdb 中的 finish 命令。 |
M-c |
等同于gdb 中的 continue 命令。 |
M-u |
等同于gdb 中的 up 命令。 |
M-d |
等同于gdb 中的 down 命令。 |
二,GDB常用调试命令
a) 调试可执行文件
以源代码为/home/zebra/目录下的test.c文件产生的可执行文件test为例(可执行文件使用gcc进行编译,并使用-g选项以产生调试信息),进行命令的说明(详细源代码参见第三部分:三,调试实例分析 )。
gdb调试源代码流程:
1,开启gdb程序,即运行如下命令: gdb -q (-q用以使得gdb不输出gdb程序的版本等信息)
2,指定调试的二进制文件:file test
3,list查看源代码
4,设定断点 breakpoint main
breakpoint sub
上述分别在main函数和sub函数处设定了断点。
断点可以设置在任意已知源代码文件的某一行,某一个函数,同时可以指定是设置在哪个/哪些线程上(见下边描述)。
5,运行可执行文件:
run
6,这样程序会运行到断点处停止下来,gdb会打印当前断点的信息。
7,使用s 或者 n进行单步调试。
s即step,n即next都是执行一条语句,然后停下来。
如果想执行一条汇编语句,则可以使用 si ,ni,即step instruction,next instruction。
8,bt命令查看当前的调用栈,bt即backtrace。
9,info frame查看函数帧信息。
10,frame n 进入某个函数帧(编号为n)
11,info 命令可以对当前的函数帧的寄存器、局部变量、函数的参数进行查看。
info register;info local;info args。
12,disassemble对当前函数对应的二进制进行反汇编。
13,x/nfu address 查看内存其中 address是内存开始的地址,从该地址向高地址增加,
x是examinate的缩写,n表示重复次数,f表示输出格式,u表示内存大小的单位(默认是字,即4个字节)。
一般我都用 x/nx address,即打印n个从address开始的内存,每个是4字节,以十六进制打印。
14,continue,执行至该函数退出
15,info threads,显示当前可调试的所有线程
16,thread <ID>,切换当前调试的线程为指定ID的线程break File:LineNumber thread <ID|ALL> if x==y。
17,thread apply <ID1 ID2...|ALL> command让一个/多个/所有线程执行GDB的命令command。
18,set scheduler-locking off|on|step,设定线程运行的锁定模式,
off表示各个线程同时进行,On表示仅当前线程可运行,step则是在执行step命令单步执行的时候,其他线程不运行。
19,q 退出调试。
20, rbreak . 在所有函数上加上断点。
rbreak REGEX
这个命令可以在所有满足正则表达式REGEX的函数上设置断点。
命令中使用的正则表达式和grep中使用的类似。
当调试C++程序的时候,rbreak用在给不属于任何class的重载函数设置断点很方便。
rbreak可以直接向一个程序的所有函数设置断点,比如:
(gdb) rbreak .
rbreak FILE:REGEX
设置断点到一个文件中的符合该正则表达式的函数上,例如:
(gdb) rbreak file.c:. 在file.c的所有函数上设置断点。
21, thread apply all backtrace 查看所有线程调用栈。
b) 调试正在运行的进程
gdb可用以调试正在运行的进程。只需要知道进程的进程号。
gdb调试进程流程:
1,gdb -p PID指定调试的进程ID号。
或者先进入gdb再指定: gdb
attach PID。
2,bt查看当前进程执行的调用栈
3,info threads查看当前可调试的线程。
其他和上述a)类似。
另: