GDB不完全手册.docx
《GDB不完全手册.docx》由会员分享,可在线阅读,更多相关《GDB不完全手册.docx(15页珍藏版)》请在冰豆网上搜索。
GDB不完全手册
GDB不完全手册
巫山霏云
使用GDB调试程序必须在被调试程序中间加入调试信息,FreePascal和GCC都是使用的–g选项,在命令行下使用如下方法:
fpc–gtemp.pas
这样编译出来的程序就带有编译信息咯,可以直接被GDB认出来。
p.s.fpc的编译选项中文解释我已经在DRS,OIBH上面公布了,有兴趣的可以去看看,也可以去我的Website查找。
在FP的IDE中可以在Option菜单下的mode中间选择Debug模式,然后编译程序,即可使编译后的程序带有调试信息。
需要说明的是没人情况下直接按F9编译出来的程序并没有带调试信息,但是当你按F7调试程序时,FP会重新按照编译模式编译一次代码,从而使你可以编译程序。
直接使用GDB有两种形式,一种从IDE里面的DeBug菜单中GDBWindow进入GDB界面。
这样可以直接使用GDB,但是仍然不是很稳定。
我不是特别推荐,当然这个也有好处,和IDE结合比较紧密。
比较好的方法是在命令行下面输入gdbtemp.exe直接进入GDB,如下:
D:
\fpc\bin\win32\fpc.exe–gE:
\prodata\program\temp\temp.pas
FreePascalCompilerversion2.0.2[2005/12/27]fori386
Copyright(c)1993-2005byFlorianKlaempfl
TargetOS:
Win32fori386
CompilingE:
\prodata\program\temp\temp.pas
LinkingE:
\prodata\program\temp\temp.exe
99Linescompiled,0.1sec
D:
\fpc\bin\win32\gdb.exeE:
\prodata\program\temp\temp.exe
GNUgdb6.2.1
Copyright2004FreeSoftwareFoundation,Inc.
GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouare
welcometochangeitand/ordistributecopiesofitundercertainconditions.
Type"showcopying"toseetheconditions.
ThereisabsolutelynowarrantyforGDB.Type"showwarranty"fordetails.
ThisGDBwasconfiguredas"i686-pc-cygwin"...
(gdb)
这样便进入了GDB调试环境。
当然你也可以进入GDB后用file再装入要调试的程序:
(gdb)filetemp.exe
Readingsymbolsfrom/cygdrive/e/prodata/program/temp/temp.exe...done.
退出呢?
quit拉,缩写就是q拉。
小心别随便输入哦,不然你设置的断点监视什么的就没有咯,下次就会比较麻烦的咯。
(gdb)是提示符,你也可以更改的,使用setpromptuserdefine厄,我比较喜欢GDB>:
(gdb)setpromptGDB>
GDB>
我们可以设置成我们喜欢的提示符,这样看起来更加好看些。
进入后你可以查看当前的语言,GDB能够自动识别你所用的编程语言,当然也有可能不能识别,这时你可以设置一下:
GDB>showlanguage
Thecurrentsourcelanguageis"auto;currentlypascal".
GDB>setlanguagepascal
GDB>showlanguage
Thecurrentsourcelanguageis"pascal".
GDB>setlanguagec
GDB>showlanguage
Thecurrentsourcelanguageis"c".
GDB>setlanguagepascal
GDB>showlanguage
Thecurrentsourcelanguageis"pascal".
GDB能够自动的识别命令的缩写,这意味着我们可以不必输入冗长的代码,而只需输入部分缩写,例如list可以缩写成l,break可以缩写成b,这样的简写还有很多。
你可以在GDB中尝试输入,如果GDB不能自动识别,也会给出所有的可能,然后让你选择。
List指令是列出代码的意思:
GDB>list
1{
2ID:
bethune1
3LANG:
PASCAL
4PROG:
beads
5}
6Var
7dat:
Array[1..350]OfChar;
8fin,fout:
Text;
9count,zoo:
Word;
10
GDB>l
11ProcedureInit;
12Var
13i:
Word;
14Begin
15Assign(fin,'beads.in');
16Reset(fin);
17Readln(fin,count);
18FillChar(dat,sizeof(dat),#0);
19Fori:
=1TocountDoRead(fin,dat[i]);
20Close(fin);
List默认列出10行代码,你也可以指定列出哪10行,用listn,这样n上下5行都会列出来,list–则显示上次显示的10行的上面的10行,具体看下面的例子:
GDB>l
57ko:
Boolean;
58i:
Word;
59Begin
60ko:
=True;
61Fori:
=1TocountDo
62Ifdat[i]<>'b'Thenko:
=False;
63IfkoThenExit(True);
64ko:
=True;
65Fori:
=1TocountDo
66Ifdat[i]<>'w'Thenko:
=False;
GDB>l
67IfkoThenExit(True);
68ko:
=True;
69Fori:
=1TocountDo
70Ifdat[i]<>'r'Thenko:
=False;
71same:
=ko;
72End;
73
74Proceduremain;
75Var
76i,tmp:
Word;
GDB>l-
57ko:
Boolean;
58i:
Word;
59Begin
60ko:
=True;
61Fori:
=1TocountDo
62Ifdat[i]<>'b'Thenko:
=False;
63IfkoThenExit(True);
64ko:
=True;
65Fori:
=1TocountDo
66Ifdat[i]<>'w'Thenko:
=False;
Run命令可以让程序运行,可以简写为r。
不过我们是来调试的,当然不要直接运行拉,调试就少不了断点,断点使用b即break来设置,用法是b行号,譬如b12,如果没有行号就是在当前设置断点,这个在进入栈调试时很有用。
也可以设置在进入某一个函数时停止,如bfind,注意:
主程序的断点名称是main,和C里面的一样的名字!
Break也有高级应用,如可以条件判断
Break…if
例如:
breakifx=1
当x=1时,程序会自动暂停!
Breakfindifi=5
当find函数中的i=5时,程序会自动暂停。
我设置了断点如何查看呢?
使用infobreak就会列出所有的断点详细信息:
GDB>b62
Breakpoint1at$4012c4:
filetemp.pas,line62.
GDB>bmain
Breakpoint2at$40149c:
filetemp.pas,line97.
GDB>infob
NumTypeDispEnbAddressWhat
1breakpointkeepy$004012c4inSAMEattemp.pas:
62
2breakpointkeepy$0040149cinmainattemp.pas:
97
设置了断点我停是停下来咯,可是我还要继续运行程序啊!
当然,我们可以使用c即continue来继续运行程序。
厄,设置错误了怎么办?
退出重新来呗!
嘿嘿,当然不要那么麻烦拉!
Del即可!
用法:
deln(n为断点号)。
那如果我要暂时使某个断点不可用怎么办啊?
disablen(n为断点号)enablen就是恢复断点的使用拉!
GDB>disable1
GDB>infob
NumTypeDispEnbAddressWhat
1breakpointkeepn$004012c4inSAMEattemp.pas:
62
2breakpointkeepy$0040149cinmainattemp.pas:
97
GDB>enable1
GDB>infob
NumTypeDispEnbAddressWhat
1breakpointkeepy$004012c4inSAMEattemp.pas:
62
2breakpointkeepy$0040149cinmainattemp.pas:
97
GDB>del1
GDB>infob
NumTypeDispEnbAddressWhat
2breakpointkeepy$0040149cinmainattemp.pas:
97
厄,断点我是知道使用了,可是只有断点也没有用啊!
我又不能查看变量的值,怎么弄啊。
呵呵,这个当然要有的拉printx(x为变量名称)。
我们先启动程序:
GDB>R
Startingprogram:
/cygdrive/e/prodata/program/temp/temp.exe
Breakpoint2,main()attemp.pas:
97
97Init;
厄,还得补充点知识,我们在FPIDE中间按F7,F8,时是步进,GDB中F7是什么指令呢?
Step!
即sn(n表示前进几步)
F8是n即next,大家自己试试吧。
和S一样的属性哦。
GDB>s
INIT()attemp.pas:
15
15Assign(fin,'beads.in');
GDB>s
16Reset(fin);
GDB>s
17Readln(fin,count);
GDB>printcount
$1=0
GDB>s
18FillChar(dat,sizeof(dat),#0);
GDB>printcount
$2=29
GDB>l
13i:
Word;
14Begin
15Assign(fin,'beads.in');
16Reset(fin);
17Readln(fin,count);
18FillChar(dat,sizeof(dat),#0);
19Fori:
=1TocountDoRead(fin,dat[i]);
20Close(fin);
21End;
22
GDB>n
19Fori:
=1TocountDoRead(fin,dat[i]);
GDB>n
20Close(fin);
GDB>n
21End;
GDB>n
main()attemp.pas:
98
98main;
Print使用还是很方便的,我们可以用来输出一个表达式的值,并输出下一行的代码。
与P类似的是echo,大家可以输入helpecho了解。
另外有个output只输出值,而不输出下一行代码,而且不把打印的值记录在历史中间。
Display可以设置一些自动显示的变量,当程序停住时,或是在但不跟踪时,这些变量会自动显示,用法:
Display
Expr为一个表达式。
如果进入一个函数了,我想直接退出怎么办啊,老在里面转很晕呢,OK,没有问题,你可以使用u即until来返回,它将运行到函数返回,除非中间还有别的断点。
可是我想用IDE中间的Watch功能呢,厄….当然还是watch拉,而且远比IDE中间的功能强大!
Watchexpexp为表达式,我们可以简单的就只要监视变量的值的改变就有咯。
而且,当你的程序运行时,倘若监视的变量的值发生了改变,程序会自动暂停下来,并输出值和下一行代码。
这样你可以很方便的查看咯!
怎么样,比IDE中间的功能强大吧,
GDB>watchi
Hardwarewatchpoint3:
I
GDB>watchcount
Hardwarewatchpoint4:
COUNT
GDB>infowatch
NumTypeDispEnbAddressWhat
1breakpointkeepy$004012c4inSAMEattemp.pas:
62
breakpointalreadyhit1time
2breakpointkeepy$0040149cinmainattemp.pas:
97
breakpointalreadyhit1time
3hwwatchpointkeepyI
4hwwatchpointkeepyCOUNT
GDB>infobreak
NumTypeDispEnbAddressWhat
1breakpointkeepy$004012c4inSAMEattemp.pas:
62
breakpointalreadyhit1time
2breakpointkeepy$0040149cinmainattemp.pas:
97
breakpointalreadyhit1time
3hwwatchpointkeepyI
4hwwatchpointkeepyCOUNT
GDB>c
Continuing.
ProgramreceivedsignalSIGTRAP,Trace/breakpointtrap.
$00401070inINIT()attemp.pas:
17
17Readln(fin,count);
GDB>printcount
$5=29
GDB>c
Continuing.
Breakpoint1,SAME()attemp.pas:
62
62Ifdat[i]<>'b'Thenko:
=False;
GDB>pi
$6=1
GDB>c
Continuing.
Breakpoint1,SAME()attemp.pas:
62
62Ifdat[i]<>'b'Thenko:
=False;
GDB>pi
$7=2
删除监视和删除断点一样的方法,直接deleten(n为编号)。
GDB>infob
NumTypeDispEnbAddressWhat
1breakpointkeepy$004012c4inSAMEattemp.pas:
62
breakpointalreadyhit3times
2breakpointkeepy$0040149cinmainattemp.pas:
97
breakpointalreadyhit1time
4hwwatchpointkeepyCOUNT
GDB>d1
GDB>infob
NumTypeDispEnbAddressWhat
2breakpointkeepy$0040149cinmainattemp.pas:
97
breakpointalreadyhit1time
4hwwatchpointkeepyCOUNT
另外还有rwatch和awatch,一个是当表达式被读时暂停程序,一个是当表达式被读或写时暂停程序。
感觉要的功能差不多了,但是我发现我的程序运行过头了,我想重新运行,怎么办啊?
晕死,这还不简单啊,看见那个X咯么?
点击就有咯啊!
厄,其实可以很简单的,输入k即kill就可以把调试的程序进程cut咯!
而且设置的断点什么全部保存咯。
不知道程序什么状态?
很简单嘛,输入infoprogram就会显示程序当前状态,运行还是ready。
GDB>k
GDB>infoprogram
Theprogrambeingdebuggedisnotbeingrun.
好拉,不完全手册到这里就基本结束咯,已经足够我们应付调试程序咯。
下面我们再次回顾GDB的常用命令:
命令
缩写
用法
作用、备注
Help
H
Hcommand
显示命令的帮助,不懂就要多多使用
File
无
Filefilename
装入要调试的可执行文件
Info
I
Infooption
option可以是program,break…..
Run
R
R
运行要调试的程序
Step
S
Sn
步进,相当于F7,n为步进次数
Next
N
Nn
下一步,相当于F8,n为下一步的次数
Continue
C
C
继续执行程序
Break
B
Boption
Option可以是num或者functioon
Watch
W
Wexp
监视表达式的值
Kill
K
K
结束当前调试的程序
Print
P
Pexp
打印表达式的值
Output
O
Oexp
同print,但是不输出下一行的语句
Echo
E
Ee
同print
Pwd
Pwd
Pwd
显示当前路径,用过linux的人都知道
infowatch|break
显示断点和监视
Delete
D
Dnum
删除编号为num的断点和监视
Showlanguage
显示当前语言
Setlanguagepascal
设置代码语言
Disable
无
Disablen
编号为n的断点暂时无效
Enable
无
Enablen
与disable相反
Diplay
无
Displayexpr
暂停,步进时自动显示表达式的值
附我的源代码:
{
ID:
bethune1
LANG:
PASCAL
PROG:
beads
}//尽管完成咯,可是还不是最佳的
Var
dat:
Array[1..350]OfChar;
fin,fout:
Text;
count,zoo:
Word;
ProcedureInit;
Var
i:
Word;
Begin
Assign(fin,'beads.in');
Reset(fin);
Readln(fin,count);
FillChar(dat,sizeof(dat),#0);
Fori:
=1TocountDoRead(fin,dat[i]);
Close(fin);
End;
Functionfind(n:
Word):
Word;
Var
k,ok,nk:
Word;
ch,tmp:
Char;
did:
Boolean;
Begin
k:
=n;
ch:
=dat[k];
tmp:
=ch;
did:
=False;
Repeat
Inc(k);
Ifk=nThenExit(count);
Ifk=count+1ThenIfnotdidThenBegink:
=1;did:
=True;EndElseBreak;
ch:
=dat[k];
Until(ch<>tmp)And(ch<>'w');
Iftmp='b'Thentmp:
='r'Elsetmp:
='b';
IfnotdidThenok:
=k-nElseok:
=count-n+k;
nk:
=k;
k:
=n;
did:
=False;
Repeat
Dec(k);
Ifk=nkThenBreak;
Ifk=0ThenIfnotdidThenBegink:
=count;did:
=True;EndElseBreak;
ch:
=dat[k];
Until(ch<>tmp)And(ch<>'w');
IfnotdidThenInc(ok,n-k)ElseInc(ok,n+count-k);
Ifok=countThenInc(ok);
Exit(ok);
End;
Functionsame:
Boolean;
Var
ko:
Boolean;
i:
Word;
Begin
ko:
=True;
Fori:
=1TocountDo
Ifdat[i]<>'b'Thenko:
=False;
IfkoThenExit(True);
ko:
=True;
Fori:
=1TocountDo
Ifdat[i]<>'w'Thenko:
=False;
IfkoThenExit(True);
ko:
=True;
Fori:
=1TocountDo
Ifdat[i]<>'r'Thenko:
=False;
same:
=ko;
End;
Proceduremain;
Var
i,tmp:
Word;
Begin
zoo:
=0;
IfsameThenBeginzoo:
=count;Exit;End;
Fori:
=1TocountDo
Begin
tmp:
=0;
Ifdat[i]<>'w'Thentmp:
=find(i);
Iftmp>zooThenzoo:
=tmp-1;
End;
End;
Procedureprint;
Begin
Assign(fout,'beads.out');
Rewrite(fout);
Writeln(fout,zoo);
Close(fout);
End;
Begin
Init;
main;
print;
End.