实时搜索: gdb如何使用

gdb如何使用

775条评论 5103人喜欢 2489次阅读 358人点赞
...

windows下怎么使用gdb: window模式下字符调试这是路径C:\Dev-Cpp\bin gdb windows 用开发工具dev-cpp,就在编译开发工具下直接执行。 如果是linux下,在所编译的文件夹中直接输入> gdb 文件名

如何用GDB进行调试: 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

如何使用gdb调试多进程:   follow-fork-mode
  在2.5.60版Linux内核及以后,GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。
  follow-fork-mode的用法为:
  set follow-fork-mode [parent|child]
  parent: fork之后继续调试父进程,子进程不受影响。
  child: fork之后调试子进程,父进程不受影响。
  因此如果需要调试子进程,在启动gdb后:
  (gdb) set follow-fork-mode child

  并在子进程代码设置断点。
  此外还有detach-on-fork参数,指示GDB在fork之后是否断开(detach)某个进程的调试,或者都交由GDB控制:
  set detach-on-fork [on|off]
  on: 断开调试follow-fork-mode指定的进程。
  off: gdb将控制父进程和子进程。follow-fork-mode指定的进程将被调试,另一个进程置于暂停(suspended)状态。
  注意,最好使用GDB 6.6或以上版本,如果你使用的是GDB6.4,就只有follow-fork-mode模式。
  follow-fork-mode/detach-on-fork的使用还是比较简单的,但由于其系统内核/gdb版本限制,我们只能在符合要求的系统上才能使用。而且,由于follow-fork-mode的调试必然是从父进程开始的,对于fork多次,以至于出现孙进程或曾孙进程的系统,例如上图3进程系统,调试起来并不方便。

如何使用arm-eabi-gdb调试android c/c++程序:

 

1.获取gdbserver

prebuilt/android-arm/gdbserver

2.获取arm-eabi-gdb

prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin

3.启动emulator(即qemu虚拟机,调式linux内核时用到)

$adb remount && adb push gdbserver /system/bin

adb shell

#gdbserver 10.0.2.2:1234 /system/bin/ping

 

$telnet localhost 5554

Trying ::1...

telnet: connect to address ::1: Connection refused

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

Android Console: type 'help' for a list of commands

OK

]

KO: unknown command, try 'help'

**cmd**redir add tcp:1234:1234

OK

exit

Connection closed by foreign host.

$cd out/target/product/generic/symbols/system/bin && arm-eabi-gdb ping

 

(gdb) r

Starting program:  

Don't know how to run.  Try "help target".

(gdb) target remote localhost:1234

Remote debugging using localhost:1234

0xb0000100 in ?? ()

(gdb) l

1779 usage();

1780 if (argc > 5)

1781 usage();

1782 } else {

1783 if (argc > 10)

1784 usage();

1785 options |= F_SOURCEROUTE;

1786 }

1787 }

1788 while (argc > 0) {

如何 gdb 如何打印一个地址中的内容: gdb查看指定地址的内存地址的值:examine 简写 x-----使用gdb> help x 来查看使用方式
x/ (n,f,u为可选参数)
n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义
f:显示格式
x(hex) 按十六进制格式显示变量。
d(decimal) 按十进制格式显示变量。
u(unsigned decimal) 按十进制格式显示无符号整型。
o(octal) 按八进制格式显示变量。
t(binary) 按二进制格式显示变量。
a(address) 按十六进制格式显示变量。
c(char) 按字符格式显示变量。
f(float) 按浮点数格式显示变量
u:每个单元的大小,按字节数来计算。默认是4 bytes。GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示

如何在gdb中打印宏定义:   gdb查看指定地址的内存地址的值:examine 简写 x-----使用gdb> help x 来查看使用方式
  x/ (n,f,u为可选参数)
  n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义
  f:显示格式
  x(hex) 按十六进制格式显示变量。
  d(decimal) 按十进制格式显示变量。
  u(unsigned decimal) 按十进制格式显示无符号整型。
  o(octal) 按八进制格式显示变量。
  t(binary) 按二进制格式显示变量。
  a(address) 按十六进制格式显示变量。
  c(char) 按字符格式显示变量。
  f(float) 按浮点数格式显示变量
  u:每个单元的大小,按字节数来计算。默认是4 bytes。GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示

如何使用GDB调试Coredump文件: 一般这种情况都是因为数组越界访问,空指针或是野指针读写造成的。程序小的话还比较好办,对着源代码仔细检查就能解决。但是对于代码量较大的程序,里边包含N多函数调用,N多数组指针访问,这时想定位问题就不是很容易了(此时牛人依然可以通过在适当位置打printf加二分查找的方式迅速定位:P)。懒人的话还是直接GDB搞起吧。 神马是Core Dump文件偶尔就能听见某程序员同学抱怨“擦,又出Core了!”。简单来说,core dump说的是操作系统执行的一个动作,当某个进程因为一些原因意外终止(crash)的时候,操作系统会将这个进程当时的内存信息转储(dump)到磁盘上1。产生的文件就是core文件了,一般会以core.xxx形式命名。 如何产生Core Dump 发生doredump一般都是在进程收到某个信号的时候,Linux上现在大概有60多个信号,可以使用 kill -l 命令全部列出来。sagi@sagi-laptop:~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX针对特定的信号,应用程序可以写对应的信号处理函数。如果不指定,则采取默认的处理方式, 默认处理是coredump的信号如下:3)SIGQUIT 4)SIGILL 6)SIGABRT 8)SIGFPE 11)SIGSEGV 7)SIGBUS 31)SIGSYS 5)SIGTRAP 24)SIGXCPU 25)SIGXFSZ 29)SIGIOT 我们看到SIGSEGV在其中,一般数组越界或是访问空指针都会产生这个信号。另外虽然默认是这样的,但是你也可以写自己的信号处理函数改变默认行为,更多信号相关可以看参考链接33。 上述内容只是产生coredump的必要条件,而非充分条件。要产生core文件还依赖于程序运行的shell,可以通过ulimit -a命令查看,输出内容大致如下:sagi@sagi-laptop:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 20 file size (blocks, -f) unlimited pending signals (-i) 16382 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) unlimited virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 看到第一行了吧,core file size,这个值用来限制产生的core文件大小,超过这个值就不会保存了。我这里输出是0,也就是不会保存core文件,即使产生了,也保存不下来==! 要改变这个设置,可以使用ulimit -c unlimited。 OK, 现在万事具备,只缺一个能产生Core的程序了,介个对C程序员来说太容易了。#include ; #include ; int crash() { char *xxx = "crash!!"; xxx[1] = 'D'; // 写只读存储区! return 2; } int foo() { return crash(); } int main() { return foo(); } 上手调试 上边的程序编译的时候有一点需要注意,需要带上参数-g, 这样生成的可执行程序中会带上足够的调试信息。编译运行之后你就应该能看见期待已久的“Segment Fault(core dumped)”或是“段错误 (核心已转储)”之类的字眼了。看看当前目录下是不是有个core或是core.xxx的文件。祭出linux下经典的调试器GDB,首先带着core文件载入程序:gdb exefile core,这里需要注意的这个core文件必须是exefile产生的,否则符号表会对不上。载入之后大概是这个样子的:sagi@sagi-laptop:~$ gdb coredump core Core was generated by ./coredump'. Program terminated with signal 11, Segmentation fault. #0 0x080483a7 in crash () at coredump.c:8 8 xxx[1] = 'D'; (gdb)我们看到已经能直接定位到出core的地方了,在第8行写了一个只读的内存区域导致触发Segment Fault信号。在载入core的时候有个小技巧,如果你事先不知道这个core文件是由哪个程序产生的,你可以先随便找个代替一下,比如/usr/bin/w就是不错的选择。比如我们采用这种方法载入上边产生的core,gdb会有类似的输出:sagi@sagi-laptop:~$ gdb /usr/bin/w core Core was generated by ./coredump'. Program terminated with signal 11, Segmentation fault. #0 0x080483a7 in ? () (gdb)可以看到GDB已经提示你了,这个core是由哪个程序产生的。 GDB 常用操作 上边的程序比较简单,不需要另外的操作就能直接找到问题所在。现实却不是这样的,常常需要进行单步跟踪,设置断点之类的操作才能顺利定位问题。下边列出了GDB一些常用的操作。 启动程序:run 设置断点:b 行号|函数名 删除断点:delete 断点编号 禁用断点:disable 断点编号 启用断点:enable 断点编号 单步跟踪:next 也可以简写 n 单步跟踪:step 也可以简写 s 打印变量:print 变量名字 设置变量:set var=value 查看变量类型:ptype var 顺序执行到结束:cont 顺序执行到某一行: util lineno打印堆栈信息:bt

怎样用gdb调试使用大量STL Container的C++程序:

原文链接:http://blog.csdn.net/luoleicn/article/details/5968038

GDB中print方法并不能直接打印STL容器中保存的变量,其实只要http://www.yolinux.com/TUTORIALS/src/dbinit_stl_views-1.03.txt这个文件保存为~/.gdbinit  就可以使用它提供的方法方便调试容器

 

Data type   GDB command  std::vector<T>    pvector stl_variable  std::list<T>  plist stl_variable T  std::map<T,T> pmap stl_variable  std::multimap<T,T>    pmap stl_variable  std::set<T>   pset stl_variable T  std::multiset<T>  pset stl_variable  std::deque<T> pdequeue stl_variable  std::stack<T> pstack stl_variable  std::queue<T> pqueue stl_variable  std::priority_queue<T>    pqueue stl_variable  std::bitset<n>td>  pbitset stl_variable  std::string pstring stl_variable  std::widestring pwstring stl_variable 

  • doc是什么格式

    oppo手机上的设置里面的格式化sd卡在哪里?: 我用的OPPO A57,设置-其他设置-存储空间-SD卡-格式化SD卡 ...

    869条评论 3774人喜欢 6457次阅读 837人点赞
  • dnf哪个图蓝色装备多

    我想了解一下vivo,oppo,华为,同价位手机2000-2500左右。买那个好,大家推荐一款!谢: vivo功能比较全,外观也好看一点,性价比真的很高 ...

    285条评论 6466人喜欢 4790次阅读 443人点赞
  • go to bed为什么to

    OPPO R11微信没有提示怎么办: 若手机来电无声,听音乐有声音,可按照以下方法排查:1、确认手机来电音量是否调到最大(手机设置--声音--音量--铃声和通知);2、先确认铃声来源,是自带铃声还是下载的第三方铃声,可更换不同铃声尝试手机来电是否有声音;...

    297条评论 4989人喜欢 4123次阅读 570人点赞
  • g大调的do在哪

    邮东西到神达宿舍地址应该怎么写: 江苏省苏州市昆山市泰山路8号神达宿舍几栋楼几层几号 邮编215300 ...

    388条评论 5361人喜欢 1574次阅读 434人点赞
  • dnf女魔法哪个好玩

    you can do great things是什么意思: you can do great things你可以做伟大的事情 例句:1.Look, you can't do things like that! 听着,你们不能再象这样做事情! ...

    202条评论 4011人喜欢 3027次阅读 551人点赞
  • .lxe文件怎么打开

    oppo手机怎么把软件安装在sd卡,移动过去真的就剩手机内存么?: 根据您的疑问,由于您没有提供具体型号,应用程序是默认安装在话机的内置存储器中,若您将手机应用程序移动到SD卡中,建议您:1.若您使用的是安装2.3以及以下的系统版本,支持将软件移动到SD卡,操作:设置-应用程序-管理...

    690条评论 3699人喜欢 4720次阅读 864人点赞