GDB
Segmentation fault 生成core
默认编译出来的程序在出现Segmentation fault 时并没有生成core崩溃文件,可以在gcc/g++编译时增加-g选项。
如果仍然没有生成core文件,则可能是因为系统设置了core文件大小为0,可以通过:ulimit -a 查询得知。
执行 ulimit -c unlimited 命令后可以使core文件大小不受限制。此时再次运行程序应该就能在同级目录看到core.XXX文件了
使用 gdb ./a.out core.XXX 可以查看出错所在行信息,这样就进入了 gdb core 调试模式。
追踪产生segmenttation fault的位置及代码函数调用情况:
gdb>bt
这样,一般就可以看到出错的代码是哪一句了,还可以打印出相应变量的数值,进行进一步分析。
ulimit -c unlimited //解除对core文件大小的限制
$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %P //默认的调参信息
sudo service apport stop //暂停服务以启用core的生成,进行gdb调试
相关命令
(1)run命令
默认情况下,以 gdb ./filename
方式启用GDB调试只是附加了一个调试文件,并没有启动这个程序,需要输入run命令(简写为r)启动这个程序
(2)continue命令
当GDB触发断点或者使用 Ctrl + C 命令中断下来后,想让程序继续运行,只要输入 continue(简写为c)命令即可。
(3)break命令
break命令(简写为b)用于添加断点,可以使用以下几种方式添加断点:
break FunctionName,在函数的入口处添加一个断点;
break LineNo,在当前文件行号为LineNo处添加断点;
break FileName:LineNo,在FileName文件行号为LineNo处添加一个断点;
break FileName:FunctionName,在FileName文件的FunctionName函数的入口处添加断点;
break -/+offset,在当前程序暂停位置的前/后 offset 行处下断点;
break … if cond,下条件断点;
(4)info break、enable、disable和delete命令
命令格式及作用:
info break,也可简写为 i b,作用是显示当前所有断点信息;
disable 断点编号,禁用某个断点,使得断点不会被触发;
enable 断点编号,启用某个被禁用的断点;
delete 断点编号,删除某个断点。
(5)backtrace和frame命令
命令格式及作用:
backtrace,也可简写为 bt,用于查看当前调用堆栈。
frame 堆栈编号,也可简写为 f 堆栈编号,用于切换到其他堆栈处。
(6)list命令
命令格式及作用:
list,输出上一次list命令显示的代码后面的代码,如果是第一次执行list命令,则会显示当前正在执行代码位置附近的代码;
list -,带一个减号,显示上一次list命令显示的代码前面的代码;
list LineNo,显示当前代码文件第 LineNo 行附近的代码;
list FileName:LineNo,显示 FileName 文件第 LineNo 行附近的代码;
list FunctionName,显示当前文件的 FunctionName 函数附近的代码;
list FileName:FunctionName,显示 FileName 文件的 FunctionName 函数附件的代码;
list from,to,其中from和to是具体的代码位置,显示这之间的代码;
list命令默认只会输出 10 行源代码,也可以使用如下命令修改:
- show listsize #查看 list 命令显示的代码行数;
- set listsize count #设置 list 命令显示的代码行数为 count;
(7)print和ptype命令
命令格式及作用:
set print pretty on //打开的格式化输出
print param,用于在调试过程中查看变量的值;
print param=value,用于在调试过程中修改变量的值;
print a+b+c,可以进行一定的表达式计算,这里是计算a、b、c三个变量之和;
print func(),输出func函数执行的结果,常见的用途是打印系统函数执行失败原因:print > strerror(errno);
print *this,在c++对象中,可以输出当前对象的各成员变量的值;
(8)whatis和ptype命令
命令格式及功能:
whatis val,用于查看变量类型;
ptype val,作用和 whatis 类似,但功能更强大,可以查看复合数据类型,会打印出该类型的成员变量。
(9)thread命令
命令格式及作用:
info thread,查看当前进程的所有线程运行情况;
thread 线程编号,切换到具体编号的线程上去;
(10)next、step命令
next 和 step 都是单步执行,但也有差别:
next 是 单步步过(step over),即遇到函数直接跳过,不进入函数内部。
step 是 单步步入(step into),即遇到函数会进入函数内部。
(11)return、finish命令
return 和 finish 都是退出函数,但也有差别:
return 命令是立即退出当前函数,剩下的代码不会执行了,return 还可以指定函数的返回值。
finish 命令是会继续执行完该函数剩余代码再正常退出。
(12)until命令
该命令使得程序执行到指定位置停下来,命令参数和 break 命令一样。
(13)jump命令
命令格式及作用:
jump LineNo,跳转到代码的 LineNo 行的位置;
jump +10,跳转到距离当前代码下10行的位置;
jump *0x12345678,跳转到 0x12345678 地址的代码处,地址前要加星号;
jump 命令有两点需要注意的:
中间跳过的代码是不会执行的;
跳到的位置后如果没有断点,那么GDB会自动继续往后执行;
(14)set args 和 show args命令
很多程序启动需要我们传递参数,set args 就是用来设置程序启动参数的,show args 命令用来查询通过 set args 设置的参数,命令格式:
set args args1,设置单个启动参数 args1;
set args “-p” “password”,如果单个参数之间有空格,可以使用引号将参数包裹起来;
set args args1 args2 args3,设置多个启动参数,参数之间用空格隔开;
set args,不带参数,则清除之前设置的参数;
(15)tbreak命令
该命令时添加一个临时断点,断点一旦被触发就自动删除,使用方法同 break。
(16)watch命令
watch 命令用来监视一个变量或者一段内存,当这个变量或者内存的值发生变化时,GDB就会中断下来。被监视的某个变量或内存地址会产生一个 watch point(观察点)。
命令格式:
watch 整型变量;
watch 指针变量,监视的是指针变量本身;
watch *指针变量,监视的是指针所指的内容;
watch 数组变量或内存区间;
(17)call命令
命令格式及作用:
call func(),执行 func() 函数,同 print func()。
(18)help命令
通过 help 命令可以查看目标命令的具体用法。