高效强大的程序调试工具——gdb(基本命令用法详解)

一、GDB概论

      gdb是GNU debugger的缩写,是编程调试工具。
      UNIX及UNIX-like(Linux)下的调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果 你是在 UNIX平台下做软件,你会发现GDB这个调试工具相比于VC的优点是具有修复网络断点以及恢复链接等功能,比BCB的图 形化调试器有更强大的功能。所谓"尺有所短,寸有所长"就是这个道理。
      只有在编译程序时加了-g选项,才能用gdb工具进行调试。


二、错误分类

      (1)编译错误:编写程序的时候没有符合语言规范导致编译错误。比如:语法错误。编译报错会明确显示哪一行出现了什么错 误,这些错误的解决方案一般来说都是比较固定的,当你写的代码够多,遇到次数多了以后,你一眼就能知道为什么自己写的程 序编译通不过,这就是经验。
      (2)运行时错误:编译器检查不出这种错误,但在运行时候可能会导致程序崩溃。比如:内存地址非法访问。这个时候我们可 以借助调试工具来快速定位程序的问题,而不是一行一行去看代码,也不是在程序中加很多的printf语句查看信息。总而言之,在 实际开发过程中,这是你必需具备的能力。
      (3)逻辑错误:编译和运行都很顺利,但是程序没有按照我们期望来执行程序。这个时候我们也要定位问题,bug出现在什么 地方。


三、功能

一般来说,GDB主要帮助你完成下面五个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事 即挂载调试。
4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。
5、当程序产生核心段错误时,可以进行CORE文件调试,查找错误。


四、使用 启动调试(前提条件,编译代码时有 -g 选项)

      (1) 用gdb启动程序进行调试
             gdb a.out

      (2) 挂载调试
            ps aux | grep a.out       --找到进程pid
            sudo gdb a.out pid       --pid为进程具体的数字id

      (3)程序核心已转储(段错误)
            gdb a.out -c core
            在程序崩溃时,一般会生成一个文件叫core文件。core文件记录的是程序崩溃时的内存映像,并加入调试信息,core文件生 成过程叫做core dump(核心已转储)。系统默认不会生成该文件。只需要简单设置即可看到core文件。

            
            设置生成core文件
            ulimit -c:查看core-dump状态。
            ulimit -c xxxx:设置core文件的大小。
            ulimit -c unlimited:core文件无限制大小。

            配置corefile的参数:
            echo 2 > /proc/sys/fs/suid_dumpable [程序中切换用户,也要产生corefile]
            mkdir /tmp/corefiles
            chmod 777 /tmp/corefiles
            echo “/tmp/corefiles/core”>/proc/sys/kernel/core_pattern //配置core文件产生的目录 为/tmp/corefiles
            echo “1” > /proc/sys/kernel/core_uses_pid

            注意:
                a.确保配置的目录有足够的磁盘空间,否则产生core文件可能不完整。
                b.对于mysqld而言,要保证正确产生core-file,需要加上–core-file,默认这个参数是不打开的。 c.kill -9 pid 是不能产生core文件的,因为SIGKILL信号不能被捕获。

            附:
          gdb 直接启动gdb,之后用file program加载程序
          gdb program 普通调试
          gdb program -c core 调试core
          sudo gdb program pid 挂载调试 程序正在运行 得用sudo权限
          sudo gdb attach pid dump已经运行进程的状态信息
          如: gdb attach pid
          (gdb) generate-core-file 调试完毕后,通过detach命令退出。
          另外,通过gcore pid命令也可以dump core文件,生成在当前目录下


五、命令

1、运行程序
      run(r)运行程序,如果要加参数,则是run arg1 arg2 …

2、查看源代码
      list(l):查看最近十行源码
      list fun:查看fun函数源代码
      list file:fun:查看flie文件中的fun函数源代码

3、设置断点与观察断点
      break 行号/fun设置断点。
      break file:行号/fun设置断点。
      break if:条件成立时程序停住。
      info break(缩写:i b):查看断点。
      watch expr:一旦expr值发生改变,程序停住。
      delete n:删除断点。

4、单步调试
      continue(c):运行至下一个断点。
      step(s):单步跟踪,进入函数,类似于VC中的step in。
      next(n):单步跟踪,不进入函数,类似于VC中的step out。
      finish:运行程序,知道当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
      until:当厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序知道退出循环体。

5、查看运行时数据
      print(p):查看运行时的变量以及表达式。
      ptype:查看类型。
      print array:打印数组所有元素。
      print *array@len:查看动态内存。len是查看数组array的元素个数。
      print x=5:改变运行时数据。


命令 命令缩写 命令说明
list l

显示多行源代码 list lineNum

在lineNum的前后源代码显示

list +列出当前行的后面代码行

list -列出当前行的前面代码行

list function 显示函数代码

set listsize count 设置显示代码的行数

show listsize    显示打印代码的行数

list first,last    显示从first到last行的源代码

break b

设置断点,程序运行到断点的位置会停下来

break[linespec] thread [threadno] [if condition]

break [filename:]line-number 使程序恰好在执行给定行之前停止

break [filename:]function-name 使程序恰好在进入指定函数之前停止

break [filename:]line-or-function if condition 如果条件成立在指定行或者函数之前停止

break [filename:]routine-name 在指定例程的入口处设置断点

断点管理:

1.显示断点信息       info break

2.删除指定断点       delete breakpoint number         不指定编号将全部删除

3.禁用断点       disable breakpoint number

4.恢复断点       enable breakpoint number

5.清除行上断点       clear number

info i

描述程序的状态

info locals       打印出当前函数中所有局部变量及其值

info args       打印出当前函数的参数名及其值

info threads       打印出当前进程的线程号及其信息

thread

info threads 查看线程
thread thread trhead_no
切换到线程thread_no thread apply all command 所有线程都执行命令打印栈桢

(1)线程锁
show scheduler-locking
set scheduler-locking on
set scheduler-locking off 默认是off,当程序继续运行的时候如果有断点,那么就把所有的线程都停下来,直到你指定某个线程 继续执行
thread trhead_no apply continue
但是如果直接在当前线程执行continue的话,默认是会启动所有线程,这种模式有一种副作用,如果 多个线程都数断在同一个函数,这时候调用会出问题。这个时候需要打开线程锁,但打开线程锁,意 味着其它线程不能运行了。

(2)non-stop模式(7.0以后的版本支持)
set target-async 1
set pagination off
set non-stop on
gdb启动了不停模式,除了断点有关的线程会被停下来,其它线程会执行

run r

开始运行程序

display disp

跟踪查看某个变量,每次停下来都显示它的值

自动打印变量的值

undisplay 取消自动打印

step s

执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句

next n

执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)

print p

打印内部变量值

p num(打印单个变量的值)

p func(1,0) 调用函数,打印其返回值

p *table 打印结构体、类、容器等数据类型和对象的数据

base@length 构造数组,显示内存块数据

如:显示在h后面的10个元素,可以使用 h@10

print h@10

p variable = value 赋值 显示

可以通过添加参数来调协输出格式:

/x   /d   /u    /o    /t(二进制格式) /a   /c    /f

continue c

设置

set vaiable = value     设置变量的值

set print elements N   指定打印的长度,对长字符串特别有用

set print elements 0   输出完整的字符串

set print pretty           设置GDB打印结构的时候,每行一个成员,并且有相应的缩进,缺省是关闭 的

start st

开始执行程序,在main函数的第一条语句前面停下来

file st

装入需要调试的程序

直接启动gdb

file a.out 加载a.out程序

kill st

开始执行程序,在main函数的第一条语句前面停下来

watch k

监视变量值的变化

watch + [变量][表达式]           当变量或表达式值发生改变,程序停住

rwatch + [变量][表达式]           当变量或表达式被读时,程序停住

awatch +[变量][表达式]           当变量或表达式被读或被写时,程序停住

catch

catch + event       当event发生时,程序停住
event可以是以下内容:

1. throw 一个C++抛出的异常   (throw为关键字)

2. throw 一个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下 有用

handle st

handle + [argu] + signals

signals:是Linux/Unix定义的信号,SIGINT表示中断字符信号,也就是Ctrl+C的信号,SIGBUS表示硬 件故障的信号;SIGCHLD表示子进程状态改变信号; SIGKILL表示终止程序运行的信号,等等。

argu:
1. nostop 当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信 号。
2.stop 当被调试的程序收到信号时,GDB会停住你的程序。
3.print 当被调试的程序收到信号时,GDB会显示出一条信息。
4.noprint 当被调试的程序收到信号时,GDB不会告诉你收到信号的信息。
5.pass or noignore 当被调试的程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给被调试程序会处理。
6.nopass or ignore 当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号。

backtrace bt

产看函数调用信息(堆栈)

frame f

查看栈帧

quit q

退出GDB环境

whatis

显示变量的类型

ptype

比whatis功能更强,可以提供一个结构的定义

examine

examine /n f u + 内存地址 (指针变量)

n表示显示内存长度

f表示输出格式

u表示字节数制定(b 单字节 h双字节 w四字节(默认) g八字节)

call

调用函数

call func(1,2)

finish结束执行当前函数,显示其返回值(如果有)

你可能感兴趣的:(linux,gdb,gcc/gdb编译调试)