简单示例
问题阐述
GDB基本使用介绍
分析问题
解决问题
常用命令
list 查看源代码
run 执行程序
print 显示数据
break 设置断点
断点管理
变量的检查和赋值
单步执行
函数的调用 : call 函数名(参数)
机器语言工具
信号
常用的gdb命令总结
查看运行时数据
表达式
程序变量
数组
输出格式
查看内存
自动显示
参考帖子
调试心得

简单示例

问题阐述

下面一段程序 : <source lang="c"> <stdio.h>

int main () {

char xuan_ze, other20;

printf ("Linux发行版真是太丰富了!\n"); printf ("1. Ubuntu\n"); printf ("2. Fedora\n"); printf ("3. Debian\n"); printf ("4. CentOS\n"); printf ("5. LFS\n"); printf ("6. Other\n"); printf ("您使用哪种Linux发行版本?(1/2/3/4/5/6) : ");

xuan_ze=getchar();

switch (xuan_ze) { case '1' : printf ("%s 是一个非常易用和友好的Linux发行版,您的选择太对了!\n","Ubuntu"); break; case '2' : printf ("%s 是一个有老牌的Linux发行版,你的选择不赖!\n","Fedora"); break; case '3' : printf ("%s 是高手是用的哦!\n","Debian"); break; case '4' : printf ("%s 是一个灵活的选择!\n","CentOS"); break; case '5' : printf ("%s ! 你和我一样喜欢折腾,握手!\n","LFS"); break; case '6' :{ printf ("哦,上面没有列到您使用的Linux,你能告诉我你使用什么版本吗?(y/n)"); xuan_ze=getchar(); if ( xuan_ze=='y') { printf ("谢谢,您使用的版本是 : \n"); scanf ("%s",other); printf ("噢,原来您使用 %s ! 这是一个不赖的选择!",other); } else printf ("不告诉我就算了!\n"); break; } default : printf ("您输入的字符好像不对,我不明白,^_^\n"); } return 0; } </source>

当前的问题是,我选择 "6" ,可是没有得到预期结果:

root@dev3-168:/data/lab/c# ./switch语句
Linux发行版真是太丰富了!
1. Ubuntu
2. Fedora
3. Debian
4. CentOS
5. LFS
6. Other
您使用哪种Linux发行版本?(1/2/3/4/5/6) : 6
哦,上面没有列到您使用的Linux,你能告诉我你使用什么版本吗?(y/n)不告诉我就算了!
root@dev3-168:/data/lab/c#

GDB基本使用介绍

为了使用 GDB 调试,需要编译支持调试:

root@dev3-168:/data/lab/c# gcc -Wall -ggdb -o switch语句 switch语句.c
root@dev3-168:/data/lab/c# gdb switch语句
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) list
1       #include <stdio.h>
2
3       int main () {
4         char xuan_ze, other[20];
5
6         printf ("Linux发行版真是太丰富了!\n");
7         printf ("1. Ubuntu\n");
8         printf ("2. Fedora\n");
9         printf ("3. Debian\n");
10        printf ("4. CentOS\n");
(gdb)

输入list可以查看源文件,接着list命令后的每一个 Enter 键都可以 继续查看下十行源文件或重复上一个list命令。

gdb 需要使用的几个命令这里说明一下:

list
列出源文件,如果第一次使用就从头列出10行源文件(gdb 下 输入 "help list" 可以得到详细文档),通常我们使用 "list 行号 " 列出此行号周围的10行文件,或者 "list -" 列出前10行,list 后的Enter键列出后10行。"list 1,20",列出1到20行。
break
设置断点,比如在34行设置断点,可以执行 break 34
watch
查看一个变量的值,注意,需要先run程序。
run
运行程序,如果设置了断点,会在断点处停下来。run后面可 以跟传递给程序的参数。
next
下一调命令,Enter键是通常都是执行上一条命令,所以我们 不用每次都敲入next命令。

分析问题

接着分析上面的问题,初步判断是 switch 语句的 case '6': 处有错 误,所以我们把断点设置在这个地方来一步一步执行程序:

(gdb)
31              printf ("%s ! 你和我一样喜欢折腾,握手!\n","LFS");
32              break;
33        case '6' :{
34              printf ("哦,上面没有列到您使用的Linux,你能告诉我你使用什么版本吗?(y/n)");
35              xuan_ze=getchar();
36              if ( xuan_ze=='y') {
37                printf ("谢谢,您使用的版本是 : \n");
38                scanf ("%s",other);
39                printf ("噢,原来您使用 %s ! 这是一个不赖的选择!",other);
40              }
(gdb) break 34
Breakpoint 1 at 0x804857f: file switch语句.c, line 34.
(gdb) run
Starting program: /data/lab/c/switch语句
Linux发行版真是太丰富了!
1. Ubuntu
2. Fedora
3. Debian
4. CentOS
5. LFS
6. Other
您使用哪种Linux发行版本?(1/2/3/4/5/6) : 6   <==注意这里,我输入了6和'\n'!

Breakpoint 1, main () at switch语句.c:34
34              printf ("哦,上面没有列到您使用的Linux,你能告诉我你使用什么版本吗?(y/n)");
(gdb) watch xuan_ze
Hardware watchpoint 2: xuan_ze
(gdb) next
35              xuan_ze=getchar();
(gdb)
Hardware watchpoint 2: xuan_ze

Old value = 54 '6'
New value = 10 '\n'   <== 原因就在这里!由于先前输入6和'\n',6被第一次取走,
                              <== '\n'还在队列里面(不清楚getchar()是怎么取值的?)
main () at switch语句.c:36
36              if ( xuan_ze=='y') {
(gdb) next
42                printf ("不告诉我就算了!\n");

原因是getchar()自己取了一个值'\n',这个getchar()有关,先面会 细说这个函数。,不过我们的问题找到答案了,可以再测试一下,在 选择的时候输入‘6y',人为地让getchar()第二次的自动取值为'y'。 看看是否符合我们的想法。

Starting program: /data/lab/c/switch语句
Linux发行版真是太丰富了!
1. Ubuntu
2. Fedora
3. Debian
4. CentOS
5. LFS
6. Other
您使用哪种Linux发行版本?(1/2/3/4/5/6) : 6y  <== 输入'6y\n' (\n代表Enter键)

Breakpoint 1, main () at switch语句.c:34
34              printf ("哦,上面没有列到您使用的Linux,你能告诉我你使用什么版本吗?(y/n)");
(gdb) watch xuan_ze
Hardware watchpoint 7: xuan_ze
(gdb) next
35              xuan_ze=getchar();
(gdb)
Hardware watchpoint 7: xuan_ze

Old value = 54 '6'
New value = 121 'y'  <== xuan_ze的值果然是'y'了!
main () at switch语句.c:36
36              if ( xuan_ze=='y') {
(gdb)
37                printf ("谢谢,您使用的版本是 : \n");
(gdb)
哦,上面没有列到您使用的Linux,你能告诉我你使用什么版本吗?(y/n)谢谢,您使用的版本是 :
38                scanf ("%s",other);
(gdb)
TurboLinux
39                printf ("噢,原来您使用 %s ! 这是一个不赖的选择!",other);
(gdb)
48        return 0;
(gdb)
49      }
(gdb)
Hardware watchpoint 7 deleted because the program has left the block
in which its expression is valid.
0xb7e8c685 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb)
Single stepping until exit from function __libc_start_main,
which has no line number information.
噢,原来您使用 TurboLinux ! 这是一个不赖的选择! <== 正确输出!
Program exited normally.

解决问题

问题找到了,getchar()总是在stdin的缓存里面去读取一个字 符,连'\n'都不放过。不能说是getchar()的bug,只能说是 getchar()的 特性。我们要么换一个其他函数交互读取字符,要么在 getchar()基础上重新设计个函数。我选择后者 ^_^,这里只是研究目 的,真正写程序的时候一定会用已有的其他函数了。

设计一个 my_getchar() 函数,它读取stdin中的第一个不为' '(空 格)或'\t'(Tab字符)的字符,作为返回字符值。它还做一个事情就是 读完 此次交互中 stdin 缓存中的所以字符。这样我们下一次再调用 my_getchar() 的时候就会重新读取用户的输入了。

char my_getchar () {
  char ch,tempch='a';
  ch=getchar();

  while (tempch!='\n') {
        if (ch==' ' || ch=='\t'){
          ch=getchar();
          continue;
        }
        else if (ch != '\n')
          tempch=getchar();
        else
          break;
  }
  return ch;
}

常用命令

在可以使用 gdb 调试程序之前,必须使用 -g 选项编译源文件。可在 makefile 中如下定义 CFLAGS 变量: CFLAGS = -g

运行 gdb 调试程序时通常使用如下的命令: gdb progname

在 gdb 提示符处键入help,将列出命令的分类,主要的分类有:

aliases               命令别名
breakpoints           断点定义
data                  数据查看
files                 指定并查看文件
internals             维护命令
running               程序执行
stack                 调用栈查看
statu                 状态查看
tracepoints           跟踪程序执行
until                 跳到某行(单步执行的时候常用)
finish                单步执行的时候,跳出进入的子函数
键入 help 后跟命令的分类名,可获得该类命令的详细清单。

list 查看源代码

(gdb) list line1,line2

run 执行程序

run命令后面可以加传递给程序的参数. set args 命令可以修改发给程 序的参数,使用 show args 可以查看传递给程序的缺省参数列表(就是 不带参数的run命令会传递给程序的参数)。

(gdb) set args 9999
(gdb) show args
Argument list to give program being debugged when it is started is "9999".
(gdb) set args -b -x -h
(gdb) show args
Argument list to give program being debugged when it is started is "-b -x -h".

print 显示数据

(gdb) print 变量  <== 查看变量值
(gdb) whatis 变量 <== 查看变量的类型

break 设置断点

break命令(简写为b),可以用来在调试的程序中设置断点,该命令有如 下四种形式:

break 行号  <== 使程序恰好在执行给定行之前停止。
break 函数名  <==  使程序恰好在进入指定的函数之前停止。
break 行号或函数名 if 条件  <==  如果condition(条件)是真,
                                              程序到达指定行或函数时停止。
break routine-name 在指定例程的入口处设置断点

如果该程序是由很多原文件构成的,你可以在各个原文件中设置断点, 而不是在当前的原文件中设置断点,其方法如下 :

(gdb) break 文件名:行号
(gdb) break 文件名:函数名

断点管理

1. 显示当前gdb的断点信息: info break

2. 删除指定的某个断点: delete breakpoint [编号]

不带编号,删除所有断点。

3. 禁止使用某个断点 : disable breakpoint 编号

4. 允许使用某个断点 :enable breakpoint 编号

5. 清除原文件中某一代码行上的所有断点 : clean 行号

变量的检查和赋值

whatis         识别数组或变量的类型
ptype          比whatis的功能更强,他可以提供一个结构的定义
set variable   将值赋予变量
print          除了显示一个变量的值外,还可以用来赋值

单步执行

next
不进入子函数的单步执行
step
进入子函数的单步执行

如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令 finish。还可以使用 until 命令跳到某行,这样也就可以跳出循环了。

函数的调用 : call 函数名(参数)

finish 结束执行当前函数。显示其返回值。

机器语言工具

有一组专用的gdb变量可以用来检查和修改计算机的通用寄存器,gdb提 供了目前每一台计算机中实际使用的4个寄存器的标准名字:

$pc : 程序计数器
$fp : 帧指针(当前堆栈帧)
$sp : 栈指针
$ps : 处理器状态

信号

常用的gdb命令总结

backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)
breakpoint 在程序中设置一个断点
cd 改变当前工作目录
clear 删除刚才停止处的断点
commands 命中断点时,列出将要执行的命令
continue 从断点开始继续执行
delete 删除一个断点或监测点;也可与其他命令一起使用
display 程序停止时显示变量和表达时
down 下移栈帧,使得另一个函数成为当前函数
frame 选择下一条continue命令的帧
info 显示与该程序有关的各种信息
jump 在源程序中的另一点开始运行
kill 异常终止在gdb 控制下运行的程序
list 列出相应于正在执行的程序的原文件内容
next 执行下一个源程序行,从而执行其整体中的一个函数
print 显示变量或表达式的值
pwd 显示当前工作目录
pype 显示一个数据结构(如一个结构或C++类)的内容
quit 退出gdb
reverse-search 在源文件中反向搜索正规表达式
run 执行该程序
search 在源文件中搜索正规表达式
set variable 给变量赋值
signal 将一个信号发送到正在运行的进程
step 执行下一个源程序行,必要时进入下一个函数
undisplay display命令的反命令,不要显示表达式
until 结束当前循环
up 上移栈帧,使另一函数成为当前函数
watch 在程序中设置一个监测点(即数据断点)
whatis 显示变量或函数类型

查看运行时数据

在你调试程序时,当程序被停住时,你可以使用print命令(简写命令为 p),或是同义命令inspect来查看当前程序的运行数据。print命令的格 式是:

print <表达式>
print /<格式> <表达式>

表达式是你所调试的程序的语言的表达式(GDB可以调试多种编程语言)。 要把表达式按16进制的格式输出,那么就是/x。

表达式

print和许多GDB的命令一样,可以接受一个表达式,GDB会根据当前的程 序运行的数据来计算这个表达式,既然是表达式,那么就可以是当前程 序运行中的const常量、变量、函数等内容。可惜的是GDB不能使用你在 程序中所定义的宏。表达式的语法应该是当前所调试的语言的语法,由 于C/C++是一种大众型的语言,所以,本文中的例子都是关于C/C++的。

在表达式中,有几种GDB所支持的操作符,它们可以用在任何一种语言中。

@        是一个和数组有关的操作符,在后面会有更详细的说明。
::         指定一个在文件或是一个函数中的变量。
{<type>} <addr>   表示一个指向内存地址<addr>的类型为type的一个对象

程序变量

在GDB中,你可以随时查看以下三种变量的值:

1、全局变量(所有文件可见的)
2、静态全局变量(当前文件可见的)
3、局部变量(当前Scope可见的)

如果你的局部变量和全局变量发生冲突(也就是重名),一般情况下是 局部变量会隐藏全局变量,也就是说,如果一个全局变量和一个函数中 的局部变量同名时,如果当前停止点在函数中,用print显示出的变量的 值会是函数中的局部变量的值。如果此时你想查看全局变量的值时,你 可以使用“::”操作符:

file::variable
function::variable

可以通过这种形式指定你所想查看的变量,是哪个文件中的或是哪个函 数中的。例如,查看文件f2.c中的全局变量x的值:

(gdb) p 'f2.c'::x

当然,“::”操作符会和C++中的发生冲突,GDB能自动识别“::” 是否C++ 的操作符,所以你不必担心在调试C++程序时会出现异常。

另外,需要注意的是,如果你的程序编译时开启了优化选项,那么在用 GDB调试被优化过的程序时,可能会发生某些变量不能访问,或是取值错 误码的情况。这个是很正常的,因为优化程序会删改你的程序,整理你 程序的语句顺序,剔除一些无意义的变量等,所以在GDB调试这种程序 时,运行时的指令和你所编写指令就有不一样,也就会出现你所想象不 到的结果。对付这种情况时,需要在编译程序时关闭编译优化。一般来 说,几乎所有的编译器都支持编译优化的开关,例如,GNU的C/C++编译 器GCC,你可以使用“-gstabs”选项来解决这个问题。关于编译器的参 数,还请查看编译器的使用说明文档。

数组

有时候,你需要查看一段连续的内存空间的值。比如数组的一段,或是 动态分配的数据的大小。你可以使用GDB的“@”操作符,“@”的左边是第一 个内存的地址的值,“@”的右边则你你想查看内存的长度。例如,你的程 序中有这样的语句:

int *array = (int *) malloc (len * sizeof (int));

于是,在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:

p *array@len

@的左边是数组的首地址的值,也就是变量array所指向的内容,右边则 是数据的长度,其保存在变量len中,其输出结果,大约是下面这个样子 的:

(gdb) p *array@len
$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}

如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有 数据的内容了。

输出格式

一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB 的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查 看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显 示格式:

    x 按十六进制格式显示变量。
    d 按十进制格式显示变量。
    u 按十六进制格式显示无符号整型。
    o 按八进制格式显示变量。
    t 按二进制格式显示变量。
    a 按十六进制格式显示变量。
    c 按字符格式显示变量。
    f 按浮点数格式显示变量。
        (gdb) p i
        $21 = 101
        (gdb) p/a i
        $22 = 0x65
        (gdb) p/c i
        $23 = 101 'e'
        (gdb) p/f i
        $24 = 1.41531145e-43
        (gdb) p/x i
        $25 = 0x65
        (gdb) p/t i
        $26 = 1100101

查看内存

你可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语 法如下所示:

x/<n/f/u> <addr>

n/f/u三个参数可以一起使用。例如: "x/3uh 0x54320" 表示,从内存 地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u 表示按十六进制显示。

自动显示

你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪 时,这些变量会自动显示。相关的GDB命令是display。

    display <expr>
    display/<fmt> <expr>
    display/<fmt> <addr>

expr是一个表达式,fmt表示显示的格式,addr表示内存地址,当你用 display设定好了一个或多个表达式后,只要你的程序被停下来,GDB会 自动显示你所设置的这些表达式的值。

格式i和s同样被display支持,一个非常有用的命令是:

display/i $pc

$pc是GDB的环境变量,表示着指令的地址,/i则表示输出格式为机器指 令码,也就是汇编。于是当程序停下后,就会出现源代码和机器指令码 相对应的情形,这是一个很有意思的功能。

下面是一些和display相关的GDB命令:

    undisplay <dnums...>
    delete display <dnums...>

删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删 除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用 减号表示(如:2-5)disable和enalbe不删除自动显示的设置,而只是 让其失效和恢复。

info display, 查看display设置的自动显示的信息。GDB会打出一张表 格,向你报告当然调试中设置了多少个自动显示设置,其中包括,设置 的编号,表达式,是否enable。

参考帖子

调试心得

[[http://www.cnblogs.com/shipfi/archive/2008/08/04/1260293.html]

1: 对于在应用程序中加入参数进行调试的方法:
   直接用 gdb app -p1 -p2 这样进行调试是不行的。
   需要像以下这样使用:
    #gdb app
    (gdb) r -p1 -p2
    或者在运行run命令前使用set args命令:
    (gdb) set args p1 p2
    可以用show args 命令来查看

2. 加入断点:
   break <linenumber>
   break <funcName>
   break +offset
   break -offset
   (在当前行号的前面或后面的offset行停住。)

   break filename:linenum
   在源文件filename的linenum行处停住。

   break filename:function
   在源文件filename的function函数的入口处停住。

  break ... if
  ...可以是上述的参数,condition表示条件,在条件成立时停住。比如在循环境体中,可以设置     break if i=100,表示当i为100时停住程序。


3. 查看运行时的堆栈:
   使用bt命令

4. 打印某个变量的值:
   print val

5. 单步: n
   继续运行: c
  step
  单步跟踪,如果有函数调用,他会进入该函数。
  next
  同样单步跟踪,如果有函数调用,他不会进入该函数。很像VC等工具中的step over。后面可以加count也可以不加,不加表示一条条地执行,加表示执行后面的count条指令,然后再停住。
  set step-mode
  set step-mode on
  打开step-mode模式,于是,在进行单步跟踪时,程序不会因为没有debug信息而不停住。这个参数有很利于查看机器码。
  set step-mod off
  关闭step-mode模式。
  finish
  运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。
  until 或 u
  当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。

6.在GDB中执行shell命令:
 在gdb环境中,你可以执行UNIX的shell的命令,使用gdb的shell命令来完成:
 eg. shell make

7. 运行环境
 可设定程序的运行路径。
  show paths 查看程序的运行路径。
  set environment varname [=value] 设置环境变量。如:set env USER=hchen
  show environment [varname] 查看环境变量。

8.观察点(WatchPoint)
  观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程 序。我们有下面的几种方法来设置观察点:
  watch
   为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。
  rwatch
   当表达式(变量)expr被读时,停住程序。
  awatch
   当表达式(变量)的值被读或被写时,停住程序。
  info watchpoints
   列出当前所设置了的所有观察点。

9. 维护breakpoint
   clear
    清除所有的已定义的停止点。
   clear func
    清除所有设置在函数上的停止点。
  delete [breakpoints] [range...]
  删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点。range 表示断点号的范围(如:3-7)。其简写命令为d。
  比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样。
  disable [breakpoints] [range...]
   disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止 点。简写命令是dis.
  enable [breakpoints] [range...]
   enable所指定的停止点,breakpoints为停止点号。


10、程序变量
查看文件中某变量的值:
file::variable
function::variable
可以通过这种形式指定你所想查看的变量,是哪个文件中的或是哪个函数中的。例如,查看文件f2.c中的全局变量x的值:
gdb) p 'f2.c'::x

查看数组的值
有时候,你需要查看一段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用GDB的“@”操作符,“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度。例如,你的程序中有这样的语句:
int *array = (int *) malloc (len * sizeof (int));
于是,在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:
p *array@len
如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有数据的内容了。



11.输出格式
一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
(gdb) p i
$21 = 101
(gdb) p/a i
$22 = 0x65
(gdb) p/c i
$23 = 101 'e'
(gdb) p/f i
$24 = 1.41531145e-43
(gdb) p/x i
$25 = 0x65
(gdb) p/t i
$26 = 1100101

11.查看内存
使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:
x/
n、f、u是可选的参数。
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。
f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。

n/f/u三个参数可以一起使用。例如:
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。

12.自动显示

你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。
display
display/
display/ expr
expr是一个表达式,fmt表示显示的格式,addr表示内存地址,当你用display设定好了一个或多个表达式后,只要你的程序被停下来,GDB会自动显示你所设置的这些表达式的值。

格式i和s同样被display支持,一个非常有用的命令是:
display/i $pc

undisplay
delete display
删除自动显示,dnums意为所设置好了的自动显式的编号。

disable display
enable display
disable和enalbe不删除自动显示的设置,而只是让其失效和恢复。

info display
查看display设置的自动显示的信息。GDB会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,其中包括,设置的编号,表达式,是否enable。

13. 设置显示选项
set print address
set print address on
打开地址输出,当程序显示函数信息时,GDB会显出函数的参数地址。系统默认为打开的,
show print address
查看当前地址显示选项是否打开。

set print array
set print array on
打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。这个选项默认是关闭的。与之相关的两个命令如下,我就不再多说了。

set print array off
show print array

set print elements
这个选项主要是设置数组的,如果你的数组太大了,那么就可以指定一个来指定数据显示的最大长度,当到达这个长度时,GDB就不再往下显示了。如果设置为0,则表示不限制。

show print elements
查看print elements的选项信息。

set print null-stop
如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示。这个选项默认为off。

set print pretty on
如果打开printf pretty这个选项,那么当GDB显示结构体时会比较漂亮。

14.关于显示源码list

以下是list命令的說明。
參數 	說明
list filename:number 	列出某檔案的第幾行,檔案是可省略的。
list [function] 	列出某函數的程式碼
list 	繼續印出程式碼
list - 	印出上一次list的程式碼的前一段程式碼(類似向上翻動)
show listsize 	顯示現在一次印出幾行
set listsize 	設定一次印出幾行



备常用命令:
  1.常看源码:list(l) 
  list <linenumber> 行号
  list <+offset> 当前行号的正偏移
  list <-offset> 当前行号的负偏移
  list <filename:linenumber> 哪个文件的哪一行
  list <function> 函数名
  list <filename:function> 文件的哪个函数
  list <*address> 程序运行时语句在内存中的地址

 2.设置断点:break(b)
  break <function> 指定函数断点
  break <linenumber> 指定行号断点
  break <+offset/-offset> 当前行号的正/负偏移
  break <filename:linenumber> 哪个文件的哪一行
  break <*address> 运行中的内存地址
  break 不带参数,下一条指令停止处
  break ... if <condition> 在运行中,当condition条件满足时停止。
    eg. break if i=100 //当i=100时,立即停止
                 break foo if i=100   //断点设置在foo中,断点条件是i-100, 一点在函数foo中,i的值等于100,被停止。



 3.查看信息:info
  info break 查看断点信息
    info locals 打印出当前函数中所有局部变量及其值
  info stack 查看栈中信息
    info frame 更详细的栈层地址信息
  info args 查看参数信息
  info registers/info all-registers 查看(所有)寄存器信息
  info sources 查看项目的源代码信息

4.维护breakpoint:disable/enable/clear/delete
     disable(dis) 【breakpoints】 【range...】
       如果没有参数,则停止所有的断点,
     enable 【breakpoints】【range】
     clear <function>/<filename:function>/<linenum>/<filename:linenum>
        清楚已定义的停止点
      delete [breakpoints] [ranga...]
         删除指定的断点

5.恢复程序运行:continue(c)
  
  
6.until和finish
  until 跳出循环比较有用
    help finish
     Execute until selected stack frame returns.
     Upon return, the value returned is printed and put in the value history.
  finish 用来跳出函数比较有用。
    help until
     Execute until the program reaches a source line greater than the current
     or a specified location (same args as break command) within the current frame