GDB十分钟教程

GDB十分钟教程

作者: liigo
原文链接: 
http://blog.csdn.net/liigo/archive/2006/01/17/582231.aspx
日期: 2006年1月16日

本文写给主要工作在Windows操作系统下而又需要开发一些跨平台软件的程序员朋友,以及程序爱好者。

GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。

GDB中的命令固然很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本的程序调试工作。

 命令 解释 示例
file <文件名>加载被调试的可执行程序文件。
因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径。
(gdb) file gdb-sample
rRun的简写,运行被调试的程序。
如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。
(gdb) r
cContinue的简写,继续执行被调试程序,直至下一个断点或程序结束。(gdb) c
b <行号>
b <函数名称>
b *<函数名称>
b *<代码地址>

d [编号]

b: Breakpoint的简写,设置断点。两可以使用“行号”“函数名称”“执行地址”等方式指定断点位置。
其中在函数名称前面加“*”符号表示将断点设置在“由编译器生成的prolog代码处”。如果不了解汇编,可以不予理会此用法。

d: Delete breakpoint的简写,删除指定编号的某个断点,或删除所有断点。断点编号从1开始递增。

(gdb) b 8
(gdb) b main
(gdb) b *main
(gdb) b *0x804835c

(gdb) d

s, ns: 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数;
n: 执行一行源程序代码,此行代码中的函数调用也一并执行。

s 相当于其它调试器中的“Step Into (单步跟踪进入)”;
n 相当于其它调试器中的“Step Over (单步跟踪)”。

这两个命令必须在有源代码调试信息的情况下才可以使用(GCC编译时使用“-g”参数)。

(gdb) s
(gdb) n
si, nisi命令类似于s命令,ni命令类似于n命令。所不同的是,这两个命令(si/ni)所针对的是汇编指令,而s/n针对的是源代码。(gdb) si
(gdb) ni
p <变量名称>Print的简写,显示指定变量(临时变量或全局变量)的值。(gdb) p i
(gdb) p nGlobalVar
display ...

undisplay <编号>

display,设置程序中断后欲显示的数据及其格式。
例如,如果希望每次程序中断后可以看到即将被执行的下一条汇编指令,可以使用命令
“display /i $pc”
其中 $pc 代表当前汇编指令,/i 表示以十六进行显示。当需要关心汇编代码时,此命令相当有用。

undispaly,取消先前的display设置,编号从1开始递增。

(gdb) display /i $pc

(gdb) undisplay 1

iInfo的简写,用于显示各类信息,详情请查阅“help i”。(gdb) i r
qQuit的简写,退出GDB调试环境。(gdb) q
help [命令名称]GDB帮助命令,提供对GDB名种命令的解释说明。
如果指定了“命令名称”参数,则显示该命令的详细说明;如果没有指定参数,则分类显示所有GDB命令,供用户进一步浏览和查询。
(gdb) help display

 

废话不多说,下面开始实践。

先给出一个示例用的小程序,C语言代码,简单的不能再简单了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

//此程序仅作为“GDB十分钟教程”的示例代码, by liigo
//Email:
liigo@sina.com
//blog: http://blog.csdn.net/liigo
//WebSite: www.liigo.com


#include
<stdio.h>

int
nGlobalVar = 0;

int
tempFunction(inta, intb)
{
    printf("tempFunction is called, a = %d, b = %d /n",a, b
);
    return (a +b
);
}


int
main()
{
    int n
;
    n = 1
;
    n
++;
    n
--;

    nGlobalVar += 100
;
    nGlobalVar -= 12
;

    printf("n = %d, nGlobalVar = %d /n",n, nGlobalVar
);

    n = tempFunction(1,2
);
    printf("n = %d",n
);

    return 0
;
}

请将此代码复制出来并保存到文件 gdb-sample.c 中,然后切换到此文件所在目录,用GCC编译之:

gcc gdb-sample.c -o gdb-sample -g

在上面的命令行中,使用 -o 参数指定了编译生成的可执行文件名为 gdb-sample,使用参数 -g 表示将源代码信息编译到可执行文件中。如果不使用参数 -g,会给后面的GDB调试造成不便。当然,如果我们没有程序的源代码,自然也无从使用 -g 参数,调试/跟踪时也只能是汇编代码级别的调试/跟踪。

下面“gdb”命令启动GDB,将首先显示GDB说明,不管它:

GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu".
(gdb) 

上面最后一行“(gdb) ”为GDB内部命令引导符,等待用户输入GDB命令。

下面使用“file”命令载入被调试程序 gdb-sample(这里的 gdb-sample 即前面 GCC 编译输出的可执行文件):

(gdb) file gdb-sample
Reading symbols from gdb-sample...done.

上面最后一行提示已经加载成功。

下面使用“r”命令执行(Run)被调试文件,因为尚未设置任何断点,将直接执行到程序结束:

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample
n = 1, nGlobalVar = 88
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

下面使用“b”命令在 main 函数开头设置一个断点(Breakpoint):

(gdb) b main
Breakpoint 1 at 0x804835c: file gdb-sample.c, line 19.

上面最后一行提示已经成功设置断点,并给出了该断点信息:在源文件 gdb-sample.c 第19行处设置断点;这是本程序的第一个断点(序号为1);断点处的代码地址为 0x804835c(此值可能仅在本次调试过程中有效)。回过头去看源代码,第19行中的代码为“n = 1”,恰好是 main 函数中的第一个可执行语句(前面的“int n;”为变量定义语句,并非可执行语句)。

再次使用“r”命令执行(Run)被调试程序:

(gdb) r
Starting program: /home/liigo/temp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;

程序中断在gdb-sample.c第19行处,即main函数是第一个可执行语句处。

上面最后一行信息为:下一条将要执行的源代码为“n = 1;”,它是源代码文件gdb-sample.c中的第19行。

下面使用“s”命令(Step)执行下一行代码(即第19行“n = 1;”):

(gdb) s
20 n++;

上面的信息表示已经执行完“n = 1;”,并显示下一条要执行的代码为第20行的“n++;”。

既然已经执行了“n = 1;”,即给变量 n 赋值为 1,那我们用“p”命令(Print)看一下变量 n 的值是不是 1 :

(gdb) p n
$1 = 1

果然是 1。($1大致是表示这是第一次使用“p”命令——再次执行“p n”将显示“$2 = 1”——此信息应该没有什么用处。)

下面我们分别在第26行、tempFunction 函数开头各设置一个断点(分别使用命令“b 26”“b tempFunction”):

(gdb) b 26
Breakpoint 2 at 0x804837b: file gdb-sample.c, line 26.
(gdb) b tempFunction
Breakpoint 3 at 0x804832e: file gdb-sample.c, line 12.

使用“c”命令继续(Continue)执行被调试程序,程序将中断在第二个断点(26行),此时全局变量 nGlobalVar 的值应该是 88;再一次执行“c”命令,程序将中断于第三个断点(12行,tempFunction 函数开头处),此时tempFunction 函数的两个参数 a、b 的值应分别是 1 和 2:

(gdb) c
Continuing.

Breakpoint 2, main () at gdb-sample.c:26
26 printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);
(gdb) p nGlobalVar
$2 = 88
(gdb) c
Continuing.
n = 1, nGlobalVar = 88

Breakpoint 3, tempFunction (a=1, b=2) at gdb-sample.c:12
12 printf("tempFunction is called, a = %d, b = %d /n", a, b);
(gdb) p a
$3 = 1
(gdb) p b
$4 = 2

上面反馈的信息一切都在我们预料之中,哈哈~~~

再一次执行“c”命令(Continue),因为后面再也没有其它断点,程序将一直执行到结束:

(gdb) c
Continuing.
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.

 

有时候需要看到编译器生成的汇编代码,以进行汇编级的调试或跟踪,又该如何操作呢?

这就要用到display命令“display /i $pc”了(此命令前面已有详细解释):

(gdb) display /i $pc
(gdb) 

此后程序再中断时,就可以显示出汇编代码了:

(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

看到了汇编代码,“n = 1;”对应的汇编代码是“movl $0x1,0xfffffffc(%ebp)”。

并且以后程序每次中断都将显示下一条汇编指定(“si”命令用于执行一条汇编代码——区别于“s”执行一行C代码):

(gdb) si
20 n++;
1: x/i $pc 0x8048363 <main+23>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x08048366 20 n++;
1: x/i $pc 0x8048366 <main+26>: incl (%eax)
(gdb) si
21 n--;
1: x/i $pc 0x8048368 <main+28>: lea 0xfffffffc(%ebp),%eax
(gdb) si
0x0804836b 21 n--;
1: x/i $pc 0x804836b <main+31>: decl (%eax)
(gdb) si
23 nGlobalVar += 100;
1: x/i $pc 0x804836d <main+33>: addl $0x64,0x80494fc

 

接下来我们试一下命令“b *<函数名称>”。

为了更简明,有必要先删除目前所有断点(使用“d”命令——Delete breakpoint):

(gdb) d
Delete all breakpoints? (y or n) y
(gdb)

当被询问是否删除所有断点时,输入“y”并按回车键即可。

下面使用命令“b *main”在 main 函数的 prolog 代码处设置断点(prolog、epilog,分别表示编译器在每个函数的开头和结尾自行插入的代码):

(gdb) b *main
Breakpoint 4 at 0x804834c: file gdb-sample.c, line 17.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample

Breakpoint 4, main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834c <main>: push %ebp
(gdb) si
0x0804834d 17 {
1: x/i $pc 0x804834d <main+1>: mov %esp,%ebp
(gdb) si
0x0804834f in main () at gdb-sample.c:17
17 {
1: x/i $pc 0x804834f <main+3>: sub $0x8,%esp
(gdb) si
0x08048352 17 {
1: x/i $pc 0x8048352 <main+6>: and $0xfffffff0,%esp
(gdb) si
0x08048355 17 {
1: x/i $pc 0x8048355 <main+9>: mov $0x0,%eax
(gdb) si
0x0804835a 17 {
1: x/i $pc 0x804835a <main+14>: sub %eax,%esp
(gdb) si
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)

此时可以使用“i r”命令显示寄存器中的当前值———“i r”即“Infomation Register”:

(gdb) i r
eax 0xbffff6a4 -1073744220
ecx 0x42015554 1107383636
edx 0x40016bc8 1073834952
ebx 0x42130a14 1108544020
esp 0xbffff6a0 0xbffff6a0
ebp 0xbffff6a8 0xbffff6a8
esi 0x40015360 1073828704
edi 0x80483f0 134513648
eip 0x8048366 0x8048366
eflags 0x386 902
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x33 51

当然也可以显示任意一个指定的寄存器值:

(gdb) i r eax
eax 0xbffff6a4 -1073744220

 

最后一个要介绍的命令是“q”,退出(Quit)GDB调试环境:




GDB 调试器使用手册


使用GDB:
   本文描述GDB,GNU的原代码调试器。(这是4.12版1994年一月,GDB版本4。16)
* 目录:
* 摘要:                        GDB的摘要
* 实例:                          一个使用实例
* 入门:                        进入和退出GDB
* 命令:                        GDB 的命令
* 运行:                        在GDB下运行程序
* 停止:                        暂停和继续执行
* 栈:                          检查堆栈
* 原文件:                      检查原文件
* 数据:                        检查数据
* 语言:                        用不同的语言来使用GDB
* 符号:                         检查符号表
* 更改:                         更改执行
* GDB的文件                     文件
* 对象                          指定调试对象
* 控制GDB                       控制
* 执行序列:                    执行一序列命令
* Emacs:                        使GDB和Emacs一起工作
* GDB的bug:
* 命令行编辑:                  行编辑
* 使用历史记录交互:
* 格式化文档:                  如何格式化和打印GDB文档

* 索引:

GDB简介:
**************

   调试器(比如象GDB)能让你观察另一个程序在执行时的内部活动,或程序出错时
发生了什么。
   GDB主要能为你做四件事(包括为了完成这些事而附加的功能),帮助你找出程序
中的错误。
   * 运行你的程序,设置所有的能影响程序运行的东西。

   * 保证你的程序在指定的条件下停止。

   * 当你程序停止时,让你检查发生了什么。

   * 改变你的程序。那样你可以试着修正某个bug引起的问题,然后继续查找另一
     个bug.

   你可以用GDB来调试C和C++写的程序。(参考 *C 和C++)


   调试Pascal程序时,有一些功能还不能使用。

  GDB还可以用来调试FORTRAN程序,尽管现在还不支持表达式的输入,输出变量,
或类FORTRAN的词法。
* GDB是"free software",大家都可以免费拷贝。也可以为GDB增加新的功能,不
过可要遵守GNU的许可协议幺。反正我认为GNU还是比较不错的:-)
就这句话:
   Fundamentally, the General Public License is a license which says
that you have these freedoms and that you cannot take these freedoms
away from anyone else.
GDB的作者:
   Richard Stallman是GDB的始作俑者,另外还有许多别的GNU的成员。许多人
为此作出了贡献。(都是老外不提也罢,但愿他们不要来找我麻烦:-))

这里是GDB的一个例子:
        原文中是使用一个叫m4的程序。但很遗憾我找不到这个程序的原代码,
所以没有办法来按照原文来说明。不过反正是个例子,我就拿一个操作系统的
进程调度原码来说明把,原代码我会附在后面。
        首先这个程序叫os.c是一个模拟进程调度的原程序(也许是个老古董了:-))。
先说明一下如何取得包括原代码符号的可执行代码。大家有心的话可以去看一下gcc的
man文件(在shell下打man gcc)。gcc -g <原文件.c> -o <要生成的文件名>
-g 的意思是生成带原代码调试符号的可执行文件。
-o 的意思是指定可执行文件名。
(gcc 的命令行参数有一大堆,有兴趣可以自己去看看。)
反正在linux下把os.c用以上方法编译连接以后就产生了可供gdb使用的可执行文件。
我用gcc -g os.c -o os,产生的可执行文档叫os.
然后打gdb os,就可进入gdb,屏幕提示:
     GDB is free software and you are welcome to distribute copies
      of it under certain conditions; type "show copying" to see
      the conditions.
     There is absolutely no warranty for GDB; type "show warranty"
      for details.

     GDB 4.16, Copyright 1995 Free Software Foundation, Inc...
 (gdb)
  (gdb)是提示符,在这提示符下可以输入命令,直到退出。(退出命令是q/Q)
为了尽量和原文档说明的命令相符,即使在本例子中没用的命令我也将演示。
首先我们可以设置gdb的屏幕大小。键入:
 (gdb)set width 70
就是把标准屏幕设为70列。
  然后让我们来设置断点。设置方法很简单:break或简单打b后面加行号或函数名
比如我们可以在main 函数上设断点:
 (gdb)break main
或(gdb)b main
 系统提示:Breakpoint 1 at 0x8049552: file os.c, line 455.
 然后我们可以运行这个程序,当程序运行到main函数时程序就会停止返回到gdb的
提示符下。运行的命令是run或r(gdb中有不少alias,可以看一下help,在gdb下打help)
run 后面可以跟参数,就是为程序指定命令行参数。
比如r abcd,则程序就会abcd以作为参数。(这里要说明的是可以用set args来指定参
数)。打入r或run后,程序就开始运行直到进入main的入口停止,显示:
Starting program: <路径>/os

Breakpoint 1, main () at os.c:455
455            Initial();
这里455 Initial();是将要执行的命令或函数。
gdb提供两种方式:1.单步进入,step into就是跟踪到函数内啦。命令是step或s
                 2.单步,next,就是简单的单步,不会进入函数。命令是next或n
这两个命令还有别的用法以后再说。
我们用n命令,键入:
(gdb)n
Success forking process# 1 ,pid is 31474

Success forking process# 2 ,pid is 31475

Success forking process# 3 ,pid is 31476


Success forking process# 5 ,pid is 31478

Success forking process# 6 ,pid is 31479

                Dispatching Algorithm : FIFO
********************************************************************************

            PCB#        PID     Priority        PC      State
            1           31474      24            0      WAITING
            2           31475      19            0      WAITING
            3           31476      16            0      WAITING
            4           31477      23            0      WAITING
            5           31478      22            0      WAITING
            6           31479      20            0      WAITING

******************************************************************************

CPU  :  NO process running
IO :  No process
Waiting CPU!!!  31474   31475   31476   31477   31478   31479
Waiting  IO    NONE
456            State=WAITING;
最后的一行就是下一句要执行的命令。我们现在在另一个函数上加断点。注意我们
可以用l/list命令来显示原代码。这里我们键入
(gdb)l
451     main()
452     {
453             int message;
454
455            Initial();
456            State=WAITING;
457            printf("Use Control-C to halt /n");
458            signal(SIGALRM,AlarmMessage);
459            signal(SIGINT,InteruptMessage);
460            signal(SIGUSR2,IoMessage);
(gdb) l
461            alarm(TimeSlot);
462            for(;;)
463             {
464             message=GetMessage();
465                   switch(message)
466                     {

468                                                     break;
469                             case CHILD_IO:          WaitingIo();
470                                                     break;
显示了原代码,现在在AlarmMessage上加断点。
(gdb) b AlarmMessage
Breakpoint 2 at 0x8048ee3: file os.c, line 259.
(gdb)
然后我们继续运行程序。
(gdb)c
c或continue命令让我们继续被中断的程序。 显示:
Continuing.
Use Control-C to halt

Breakpoint 2, AlarmMessage () at os.c:259
259             ClearSignal();
注意我们下一句语句就是ClearSignal();
我们用s/step跟踪进入这个函数看看它是干什么的。
(gdb) s
ClearSignal () at os.c:227
227             signal(SIGINT,SIG_IGN);
用l命令列出原代码:
(gdb) l
222     }
223
224
225     void ClearSignal()    /* Clear other signals */
226     {
227             signal(SIGINT,SIG_IGN);
228             signal(SIGALRM,SIG_IGN);
229             signal(SIGUSR2,SIG_IGN);
230     }
231
(gdb)
我们可以用s命令继续跟踪。现在让我们来试试bt或backtrace命令。这个命令可以
显示栈中的内容。
(gdb) bt
#0  ClearSignal () at os.c:227
#1  0x8048ee8 in AlarmMessage () at os.c:259
#2  0xbffffaec in ?? ()
#3  0x80486ae in ___crt_dummy__ ()
(gdb)
大家一定能看懂显示的意思。栈顶是AlarmMessage,接下来的函数没有名字--就是
没有原代码符号。这显示了函数调用的嵌套。
好了,我们跟踪了半天还没有检查过变量的值呢。检查表达式的值的命令是p或print
格式是p <表达式>
444444让我们来找一个变量来看看。:-)
(gdb)l 1
还记得l的作用吗?l或list显示原代码符号,l或list加<行号>就显示从<行号>开始的
原代码。好了找到一个让我们来看看WaitingQueue的内容
(gdb) p WaitingQueue
$1 = {1, 2, 3, 4, 5, 6, 0}
(gdb)
WaitingQueue是一个数组,gdb还支持结构的显示,
(gdb) p Pcb
$2 = {{Pid = 0, State = 0, Prior = 0, pc = 0}, {Pid = 31474, State = 2,
    Prior = 24, pc = 0}, {Pid = 31475, State = 2, Prior = 19, pc = 0}, {
    Pid = 31476, State = 2, Prior = 16, pc = 0}, {Pid = 31477, State = 2,
    Prior = 23, pc = 0}, {Pid = 31478, State = 2, Prior = 22, pc = 0}, {
    Pid = 31479, State = 2, Prior = 20, pc = 0}}
(gdb)
这里可以对照原程序看看。
原文档里是一个调试过程,不过我想这里我已经把gdb的常用功能介绍了一遍,基本上
可以用来调试程序了。:-)

运行GDB(一些详细的说明):

  前面已经提到过如何运行GDB了,现在让我们来看一些更有趣的东西。你可以在运行
GDB时通过许多命令行参数指定大量的参数和选项,通过这个你可以在一开始就设置好
程序运行的环境。
  这里将要描述的命令行参数覆盖了大多数的情况,事实上在一定环境下有的并没有
什么大用处。最通常的命令就是使用一个参数:
 $gdb <可执行文档名>
你还可以同时为你的执行文件指定一个core文件:
 $gdb <可执行文件名> core
你也可以为你要执行的文件指定一个进程号:
 $gdb <可执行文件名> <进程号> 如:&gdb os 1234将使gdb与进程1234相联系(attach)
除非你还有一个文件叫1234的。gdb首先检查一个core文件。
如果你是使用一个远程终端进行远程调试的话,那如果你的终端不支持的话,你将无法
使用第二个参数甚至没有core dump。如果你觉得开头的提示信息比较碍眼的话,你可以
用gdb -silent。你还可以用命令行参数更加详细的控制GDB的行为。
打入gdb -help或-h 可以得到这方面的提示。所有的参数都被按照排列的顺序传给gdb
除非你用了-x参数。
  当gdb开始运行时,它把任何一个不带选项前缀的参数都当作为一个可执行文件或core
文件(或进程号)。就象在前面加了-se或-c选项。gdb把第一个前面没有选项说明的参数
看作前面加了-se 选项,而第二个(如果有的话)看作是跟着-c选项后面的。
  许多选项有缩写,用gdb -h可以看到。在gdb中你也可以任意的把选项名掐头去尾,只
要保证gdb能判断唯一的一个参数就行。
在这里我们说明一些最常用的参数选项
-symbols <文件名>(-s <文件名>)------从<文件名>中读去符号。
-exec <文件名>(-e <文件名>)----在合适的时候执行<文件名>来做用正确的数据与core
 dump的作比较。
-se <文件名>------从<文件名>中读取符号并把它作为可执行文件。
-core <文件名>(-c <文件名>)--指定<文件名>为一个core dump 文件。
-c <数字>----连接到进程号为<数字>,与attach命令相似。
-command <文件名>
-x <文件名>-----执行gdb命令,在<文件名>指定的文件中存放着一序列的gdb命令,就
象一个批处理。
-directory(-d) <路径>---指定路径。把<路径>加入到搜索原文件的路径中。
-m
-mapped----
   注意这个命令不是在所有的系统上都能用。如果你可以通过mmap系统调用来获得内存
映象文件,你可以用这个命令来使gdb把你当前文件里的符号写入一个文件中,这个文件
将存放在你的当前路径中。如果你调试的程序叫/temp/fred那么map文件就叫
./fred.syms这样当你以后再调试这个程序时,gdb会认识到这个文件的存在,从而从这
个文件中读取符号,而不是从可执行文件中读取。.syms与主机有关不能共享。
-r
-readnow---马上从符号文件中读取整个符号表,而不是使用缺省的。缺省的符号表是
调入一部分符号,当需要时再读入一部分。这会使开始进入gdb慢一些,但可以加快以后
的调试速度。

 -m和-r一般在一起使用来建立.syms文件


接下来再谈谈模式的设置(请听下回分解 :-))
附:在gdb文档里使用的调试例子我找到了在minix下有这个程序,叫m4有兴趣的
可以自己去看看


模式的选择
--------------
现在我们来聊聊gdb运行模式的选择。我们可以用许多模式来运行gdb,例如在“批模式”
或“安静模式”。这些模式都是在gdb运行时在命令行作为选项指定的。
`-nx'
`-n'
     不执行任何初始化文件中的命令。(一般初始化文件叫做`.gdbinit').一般情况下在

`-quiet'
`-q'
     “安静模式”。不输出介绍和版权信息。这些信息在“批模式”中也被跳过。

`-batch'
     “批模式”。在“批模式”下运行。当在命令文件中的所有命令都被成功的执行后
     gdb返回状态“0”,如果在执行过程中出错,gdb返回一个非零值。
     “批模式”在把gdb作为一个过滤器运行时很有用。比如在一台远程计算机上下载且
     执行一个程序。信息“ Program exited normally”(一般是当运行的程序正常结束
     时出现)不会在这种模式中出现。
`-cd DIRECTORY'
     把DIRECTORY作为gdb的工作目录,而非当前目录(一般gdb缺省把当前目录作为工作目
     录)。
`-fullname'
`-f'
     GNU Emacs 设置这个选项,当我们在Emacs下,把gdb作为它的一个子进程来运行时,
     Emacs告诉gdb按标准输出完整的文件名和行号,一个可视的栈内容。这个格式跟在
     文件名的后面。行号和字符重新按列排,Emacs-to-GDB界面使用/032字符作为一个
     显示一页原文件的信号。
`-b BPS'
     为远程调试设置波特率。

`-tty DEVICE'
     使用DEVICE来作为你程序的标准输入输出。

(gdb) q
The program is running. Exit anyway? (y or n) y

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454056.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

课后作业-阅读任务-阅读提问-3

1.如果两个人合作的始终达不到规范阶段该怎如何处理&#xff1f; 2. 逻辑和界面设计要注意哪些因素&#xff1f;转载于:https://www.cnblogs.com/fhycm/p/7866548.html

ride上点击用例不能显示edit信息_接口测试平台代码实现61: 多接口用例1

终于又序更上了&#xff0c;原谅最近作者几天事情不断。按照我们之前的计划&#xff0c;需要迅速开启很重要的核心多用例接口。首先&#xff0c;我们要确定&#xff0c;这个功能的大体设计。就放在在我们的页面 用例库 中&#xff1a;所以也就是我们很久之前就创建好的P_cases.…

黑客攻防专题八:21种RING的提权方法

好多都没有成功&#xff0c;还是发来看看&#xff0c;看看思路&#xff0c;呵呵 以下全部是本人提权时候的总结 很多方法至今没有机会试验也没有成功&#xff0c;但是我是的确看见别人成功过的。本人不才&#xff0c;除了第一种方法自己研究的&#xff0c;其他的都是别人的经验…

Linux 状态命令之内存状态 free

简介 free指令会显示内存的使用情况&#xff0c;包括实体内存&#xff0c;虚拟的交换文件内存&#xff0c;共享内存区段&#xff0c;以及系统核心使用的缓冲区等。 语法 free [-bkmotV][-s <间隔秒数>]参数说明&#xff1a;-b  以Byte为单位显示内存使用情况。-k  以…

SpringMVC在使用Jackson2时关于日期类型格式化的问题

*本例程序使用Jackson2.9.0&#xff0c;jackson1.x的处理方式稍稍有些不同。 在基于Spring&SpringMVC的Web项目中&#xff0c;我们常使用Jackson(1.x/2.x)来增加程序对Json格式的数据的支持。 因此&#xff0c;在实际应用中有个常见的需求&#xff1a;日期的格式化。 假设&…

GDB 使用——Linux C编程

简述 一 列文件清单 二&#xff1a;执行程序 三&#xff1a;显示数据 四&#xff1a;断点(breakpoint) 五&#xff0e;断点的管理 六&#xff0e;变量的检查和赋值 七. 单步执行 八&#xff0e;函数的调用 九&#xff0e;机器语言工具 …

python拨号_python 拨号代码(win10 系统亲测有效)

# -*- coding: utf-8 -*-import win32rasimport time,osdef Connect(dialname, account, passwd):dial_params (dialname, , , account, passwd, )return win32ras.Dial(None, None, dial_params, None)def DialBroadband():dialname u宽带连接 #just a nameaccount u059291…

HP服务器引导盘下载地址

HP SmartStart CD 8.7 x32版本的下载地址为&#xff1a;http://ftp.hp.com/pub/softlib2/software1/cd/p1040463476/v63549/smartstart-8.70-0-x86.zip HP SmartStart CD 8.7 x32版本支持以下机型&#xff1a; HP ProLiant ML 和 DL 300、500 和 700 系列以及 HP ProLiant BL S…

MUI - 预加载

打开详情页回到顶部:document.body.scrollTop document.documentElement.scrollTop 0;方式一&#xff1a;preload一次仅能预加载一个页面&#xff08;除非循环&#xff09; var subWebview mui.preload({url: examples/accordion.html,id: template_sub,top: styles: {48 …

python 分类变量xgboost_【转】XGBoost参数调优完全指南(附Python代码)

xgboost入门非常经典的材料&#xff0c;虽然读起来比较吃力&#xff0c;但是会有很大的帮助&#xff1a;英文原文链接:https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning-xgboost-with-codes-python/

用 GDB 调试Linux程序及有用技巧

用 GDB 调试Linux程序及有用技巧(转) armlinux 2008-06-19 10:48 阅读91 评论0 字号&#xff1a; 大大 中中 小小 GNU的调试器称为gdb&#xff0c;该程序是一个交互式工具&#xff0c;工作在字符模式。在 X Window 系统中&#xff0c;有一个gdb的前端图形工具…

Bash : 索引数组

Bash 提供了两种类型的数组&#xff0c;分别是索引数组(indexed array)和关联数组(associative array)。本文主要介绍索引数组的基本用法。 索引数组的基本特点 Bash 提供的数组都是一维数组。任何变量都可以用作索引数组。通过 declare 关键字可以显式的声明一个索引数组。数组…

Flask 第三方组件之 login

在了解使用Flask来实现用户认证之前&#xff0c;我们首先要明白用户认证的原理。假设现在我们自己去实现用户认证&#xff0c;需要做哪些事情呢&#xff1f; 首先&#xff0c;登录。用户能够输入用户名和密码进行登录&#xff0c;所以需要网页和表单&#xff0c;实现用户输入和…

Zookeeper客户端Curator使用详解

http://www.jianshu.com/p/70151fc0ef5dZookeeper客户端Curator使用详解 简介 Curator是Netflix公司开源的一套zookeeper客户端框架&#xff0c;解决了很多Zookeeper客户端非常底层的细节开发工作&#xff0c;包括连接重连、反复注册Watcher和NodeExistsException异常等等。Pat…

python argparse nargs_Python | 使用argparse解析命令行参数

今天是Python专题第27篇文章&#xff0c;我们来聊聊Python当中的命令行参数工具argparse。命令行参数工具是我们非常常用的工具&#xff0c;比如当我们做实验希望调节参数的时候&#xff0c;如果参数都是通过硬编码写在代码当中的话&#xff0c;我们每次修改参数都需要修改对应…

Python 第三方模块之 smtplib

1 python对SMTP的支持 SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;是简单传输协议&#xff0c;它是一组用于用于由源地址到目的地址的邮件传输规则。 python中对SMTP进行了简单的封装&#xff0c;可以发送纯文本邮件、HTML邮件以及带附件的邮件。两个核心模块…

Node.js 使用jQuery取得Nodejs http服务端返回的JSON对象示例

server.js代码&#xff1a; // 内置http模块&#xff0c;提供了http服务器和客户端功能&#xff08;path模块也是内置模块&#xff0c;而mime是附加模块&#xff09; var httprequire("http");// 创建服务器,创建HTTP服务器要调用http.createServer()函数&#xff0c…

linux下gdb单步调试

用 GDB调试程序 GDB 概述 ———— GDB 是 GNU开源组织发布的一个强大的 UNIX下的程序调试工具。或许&#xff0c;各位比较喜欢那种图形界面方式的&#xff0c;像 VC、 BCB等 IDE的调试&#xff0c;但如果你是在 UNIX平台下做软件&#xff0c;你会发现 GDB这个调试工具有比 V…

svg 动画_根据AI导出的SVG path制作SVG线条动画

点击右上方红色按钮关注“web秀”&#xff0c;让你真正秀起来前言首先祝大家2019新年快乐&#xff0c;万事大吉&#xff0c;猪事顺利&#xff0c;阖家欢乐。前面文章SVG 线条动画基础入门知识学习到了基础知识&#xff0c;现在来给大家讲讲如何制作SVG 制作复杂图形线条动画。假…

MySQL提示Truncated incorrect DOUBLE value解决方法

“Truncated incorrect DOUBLE value”的解决方法主要是这两种&#xff1a; 1、修改了多个列的值而各列之间用逗号连接而不要用and 错误写法示例&#xff1a;update tablename set col1value1 and col2value2 where col3value3&#xff1b;正确写法示例&#xff1a;update ta…