多进程 多线程调试方法 GDB调试 .
使用GDB调试多线程实例详解

使⽤GDB调试多线程实例详解
先写⼀段多线程程序。
makefile
加上 -g参数⽣成可调式信息,可以进⾏调试。
pthread不是Linux下的默认的库,也就是在链接的时候,⽆法找到phread库中哥函数的⼊⼝地址,于是链接会失败。
在gcc编译的时候,附加要加 -lpthread参数即可解决。
gdb test 进⼊调试
需要调试的地⽅打下断点,run运⾏到断点处。
r 运⾏到断点处,info thread可以查看被调试的线程。
thread apply all bt 让所有线程打印堆栈信息
set scheduler-locking off|on|step
在使⽤step或continue命令调试当前被调试线程的时候,其他线程也是同时执⾏的,如果我们只想要被调试的线程执⾏,⽽其他线程停⽌等待,那就要锁定要调试的线程,只让它运⾏。
off:不锁定任何线程,所有线程都执⾏。
on:只有当前被调试的线程会执⾏。
step:阻⽌其他线程在当前线程单步调试的时候抢占当前线程。
只有当next、continue、util以及finish的时候,其他线程才会获得重新运⾏的。
show scheduler-locking:
这条命令是为了查看当前锁定线程的模式。
感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。
GDB调试简易教程

GDB调试简易教程GDB(GNU调试器)是一个开源的调试工具,它用于调试C、C++和其他编程语言的程序。
它允许程序员在执行过程中观察程序的内部状态,帮助找到程序中的错误并进行修复。
下面是一个简易的GDB调试教程,以帮助你入门并学会使用它。
安装GDB首先,你需要在你的系统上安装GDB。
对于大多数Linux发行版,你可以通过在终端中运行以下命令来安装它:```sudo apt-get install gdb```编译程序在使用GDB之前,你需要编译你的程序,并在编译时使用-g选项,以便生成调试信息。
例如,对于C语言程序,你可以使用以下命令来编译:```gcc -g program.c -o program```这将生成一个可执行文件program,并在目录中生成调试信息。
启动GDB在终端中使用以下命令来启动GDB并调试你的程序:```gdb program```这将启动GDB,并且你将看到GDB的命令提示符。
设置断点断点是你在程序中指定的一个位置,当程序执行到该位置时会暂停。
你可以使用断点来观察程序在这一点的状态。
要设置断点,请在GDB的命令提示符下输入以下命令:```break line_number```line_number是你想要设置断点的源代码行号。
例如,要在程序的第10行设置断点,你可以使用以下命令:```break 10```或者你也可以使用函数名作为参数来设置断点:```break function_name```开始调试一旦设置好断点,你可以开始调试你的程序了。
要开始执行程序,请输入以下命令:```run```程序将开始运行直到第一个断点处。
此时,程序会停下来并且GDB会等待你的进一步命令。
观察变量在程序运行到断点处时,你可以使用以下命令来观察程序内部的变量值:```print variable_name```variable_name是你想要观察的变量的名称。
例如,要查看变量x的值,你可以使用以下命令:```print x```你还可以通过使用其他GDB命令来观察更多的变量信息,例如观察数组、结构体等。
gdb 调试方法

gdb 调试方法
GDB 是一款功能强大的调试工具,它可以用于调试C、C++、Python 等编程语言的代码。
下面是一些常用的 GDB 调试方法:
1. 设置断点:可以使用`break` 命令在代码的某一行设置断点,例如 `break main.c:10` 表示在 main.c 文件的第 10 行设置断点。
2. 运行程序:使用 `run` 命令来运行程序,例如 `run arg1 arg2` 表示运行程序并传入参数 arg1 和 arg2。
3. 单步执行:可以使用 `step` 命令以单步方式执行代码,进入
函数时会逐行执行其中的代码。
4. 查看变量值:使用 `print` 命令可以查看变量的值,例如
`print x` 表示打印变量 x 的值。
5. 修改变量值:使用 `set` 命令可以修改变量的值,例如 `set x = 10` 表示将变量 x 的值设置为 10。
6. 查看函数调用栈:使用 `backtrace` 或 `bt` 命令可以打印函数调用栈。
7. 继续执行:使用 `continue` 命令可以继续执行程序直到下一
个断点或程序结束。
8. 异常处理:可以使用 `catch` 命令来设置异常断点,例如
`catch throw` 表示在抛出异常时停止程序执行。
9. 调试多线程程序:GDB 支持调试多线程程序,可以使用
`thread` 命令来操作线程,例如 `thread 2` 表示切换到线程 2 进行调试。
以上是一些常用的 GDB 调试方法,通过掌握这些方法可以更好地使用 GDB 进行程序的调试。
同时,GDB 还提供了更多强大的调试功能,可以根据具体需求来进一步探索和学习。
gdb调试技巧

gdb调试技巧GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。
它是一种强大的命令行调试工具。
一般来说,调试器的功能:能够运行程序,设置所有能影响程序运行的参数;能够让程序在指定条件下停止运行;能够在程序停止时检查所有参数的情况;能够根据指定条件改变程序的运行。
gdb调试源代码流程:1)进入GDB #gdb test只需输入GDB和要调试的可执行文件即可,在GDB的启动画面中指出了GDB的版本号、遵循的许可等信息,接下来就进入了由"(gdb)"开头的命令行界面了;2)查看文件(gdb) l在GDB中键入"l"(list)就可以查看程序的源码了,GDB列出的源代码中明确地给出了对应的行号,方便代码的定位;3)设置断点(gdb) b 6只需在"b"(break)后加入对应的行号即可,在GDB中利用行号设置断点是指代码运行到对应行之前暂停;设置断点可以使程序执行到某个位置时暂停,程序员在该位置处可以方便地查看变量的值、堆栈情况等;一般情况下,源代码中大家行号与用户书写程序的行号是一致的,但有时由于用户的某些编译选项会导致行号不一致的情况,因此,一定要查看在GDB中的行号;4)查看断点处情况(gdb) info b可以键入"info b"来查看断点处情况,可以设置多个断点;5)运行代码(gdb) rGDB默认从首行开始运行代码,键入"r"(run)即可;程序运行到断点处停止。
6)看变量值(gdb) p n在程序暂停之后,程序员可以查看断点处的相关变量值,在GDB 中只需键入"p 变量名"(print)即可;GDB在显示变量值时都会在对应值之前加上"$N"标记,它是当前变量值的引用标记,以后若想再次引用此变量,就可以直接写作"$N",而无需写冗长的变量名;7)观察变量(gdb) watch n在某一循环处,往往希望能够观察一个变量的变化情况,这时就可以键入命令"watch"来观察变量的变化情况,GDB在"n"设置了观察点;8)单步运行(gdb) n单步运行是指一次只运行一条语句,这样可以方便查看程序运行的结果,在此处只需键入"n"(next)即可;随着程序的单步运行,当变量n的值发生变化时,GDB就会自动显示出n的变化情况。
gdb调试方法

gdb调试方法
GDB是一款功能强大的调试器,可以帮助开发人员快速定位和解决程序中的错误。
以下是GDB调试的一些常用方法:
1. 启动程序:在终端中输入gdb programname,其中programname 是要调试的程序的名称。
2. 设置断点:使用break命令设置断点,例如break functionname,在函数functionname处设置断点。
3. 运行程序:使用run命令运行程序,程序会在设置的断点处停止执行。
4. 单步执行:使用单步命令step或next执行程序,step命令会进入函数内部,next命令则不会。
5. 查看变量值:使用print命令查看变量的值,例如print varname。
6. 修改变量值:使用set命令修改变量的值,例如set varname=newvalue。
7. 查看函数调用栈:使用backtrace命令查看函数调用栈,可以确定程序执行到哪个函数。
8. 调试多线程程序:可以使用thread命令查看和切换线程,使用info threads命令查看线程的状态。
9. 导出调试信息:使用gdb -batch -ex 'info functions' programname > function_list.txt命令将程序的函数列表导出到文件中。
以上是GDB调试的一些常用方法,熟练掌握这些方法可以帮助开发人员快速排除程序中的错误。
gdb 多线程调试原理

GDB(GNU Debugger)是一个功能强大的调试器,它能够解决并发程序调试的难题。
在多线程调试中,其主要任务是准确及时地捕捉被调试程序线程状态的变化的事件,并且GDB针对捕捉到的事件做出相应的操作。
GDB的工作原理可以概括为以下几个步骤:首先,在编译程序时,通常会生成调试信息,包括源代码和符号表。
符号表记录了程序中的函数、变量和类型信息。
然后,GDB会将这些信息与被调试的程序进行匹配,从而确定程序的状态。
最后,GDB会根据用户的命令,控制程序的执行,例如设置断点、单步执行等。
在Linux平台,GDB实现多线程调试主要依赖三个文件:thread.c、infrun.c和symtab.c。
其中,thread.c文件的任务非常简单,就是多线程调试命令子集的实现,比如"info threads"。
当用户在gdb命令行敲入多线程调试命令子集中的命令时,就会调用thread.c中对应的函数。
而GDB对于线程列表的维护工作主要在infrun.c和symtab.c两个文件中实现。
此外,GDB还支持查看程序运行时的内存内容和寄存器状态。
在调试多进程程序时,GDB 默认只追踪父进程,但可以通过命令设置,实现只追踪父进程或子进程,或者同时调试父进程和子进程。
这为调试并发程序或多线程应用程序提供了极大的便利。
gdb调试案例

gdb调试案例以GDB调试案例为题,我将列举以下10个案例,每个案例将描述GDB的使用场景、调试目标、具体步骤和调试结果,以帮助读者更好地理解和掌握GDB调试工具。
案例一:查看程序崩溃的原因场景:当程序崩溃时,我们需要找出崩溃的原因,以便修复程序中的bug。
目标:在程序崩溃时,使用GDB查看崩溃的原因。
步骤:1. 使用-g选项编译程序,以包含调试信息。
2. 执行gdb命令,加载可执行文件。
3. 在GDB中运行程序,当程序崩溃时,GDB会自动停止程序的执行。
4. 使用backtrace命令查看调用栈,找出导致崩溃的函数和行号。
5. 使用print命令查看变量的值,以便进一步分析崩溃原因。
结果:通过查看调用栈和变量的值,我们可以定位到导致程序崩溃的具体代码行,并进行修复。
案例二:设置断点并跟踪程序执行场景:当程序运行过程中出现问题,我们需要跟踪程序的执行过程,以便找出问题所在。
目标:使用GDB设置断点并跟踪程序执行。
步骤:1. 使用-g选项编译程序,以包含调试信息。
2. 执行gdb命令,加载可执行文件。
3. 使用break命令设置断点,可以选择在特定函数或行号上设置断点。
4. 运行程序,GDB会在断点处停止程序的执行。
5. 使用step命令逐行执行程序,并查看变量的值。
6. 使用continue命令继续程序的执行,直到下一个断点或程序结束。
结果:通过设置断点和逐行执行程序,我们可以跟踪程序的执行过程,找出问题所在。
案例三:查看内存信息场景:当程序出现内存相关的问题时,我们需要查看程序的内存使用情况,以便分析问题所在。
目标:使用GDB查看程序的内存信息。
步骤:1. 使用-g选项编译程序,以包含调试信息。
2. 执行gdb命令,加载可执行文件。
3. 运行程序,GDB会自动停止程序的执行。
4. 使用info breakpoints命令查看已设置的断点。
5. 使用info registers命令查看寄存器的值。
GDB调试技巧与实战

GDB调试技巧与实战GDB(GNU调试器)是一种强大的调试工具,广泛用于C/C++程序的调试。
它具有许多有用的功能和命令,可以帮助我们快速定位和解决程序中的bug。
在本文中,我将介绍一些GDB调试技巧和实例,帮助您更好地使用GDB进行调试工作。
1. 启动程序:要使用GDB调试程序,我们需要在启动GDB时将程序作为参数传递给它。
例如,要调试名为myprogram的可执行文件,可以使用以下命令启动GDB:```gdb myprogram```2. 设置断点:当我们想要在特定位置暂停程序执行时,可以在该位置设置断点。
使用GDB的"break"命令可以实现。
例如,要在程序的main 函数处设置断点,可以使用以下命令:```break main```我们还可以使用行号来设置断点,例如:```break file.c:10```3. 运行程序:设置了断点后,我们可以使用GDB的"run"命令来运行程序。
程序会在达到断点时暂停执行。
例如:```run```如果程序需要命令行参数,我们可以在run命令后面添加参数。
例如:```run arg1 arg2```4. 单步调试:一旦程序暂停在断点处,可以使用GDB的"step"命令逐行执行程序。
这对于理解程序的执行流程非常有用。
例如:```step```如果希望在函数内部逐行执行,可以使用"next"命令。
它会跳过函数内部的细节,直接进入下一行。
例如:```next```5. 打印变量:在调试程序时,我们经常需要查看变量的值。
GDB的"print"命令可以用于打印变量的值。
例如,要打印整型变量x的值,可以使用以下命令:```print x```我们还可以使用GDB的表达式语言来计算表达式的值。
例如,要打印变量x和y的和,可以使用以下命令:```print x + y```6. 查看堆栈:GDB可以帮助我们查看程序的堆栈跟踪信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[root@tivf09 root]# ps -ef|grep -i vnc
root 19609 1 0 Jun05 ?
00:08:46 Xvnc :1 -desktop
tivf09:1 (root)
-httpd /usr/share/vnc/classes -auth /root/.Xauthority
-geometry 1024x768
-depth 16 -rfbwait 30000 -rfbauth /root/.vnc/passwd -rfbport
5901 -pn
root 19627 1 0 Jun05 ?
00:00:00 vncconfig
-iconic
root 12714 10599 0 01:23 pts/0 00:00:00 grep -i vnc
Attach 子进程
众所周知,GDB 有附着(attach)到正在运行的进程的功能,即 attach <pid>命令。因此我们可以利用该命令 attach 到子进程然后进行调试。
例如我们要调试某个进程 RIM_Oracle_Agent.9i,首先得到该进程的 pid
[root@tivf09 tianq]# ps -ef|grep RIM_Oracle_Agent.9i
3、GDB wrapper 方法:专用于 fork+exec 模式,不用添加额外代码, 但需要 X 环境支持(xterm/VNC)这种方式没有使用过,一般对于企业 开发的话是不是很多都没有 x 环境支持的吧(猜测:))
follow-fork-mode 方式比较简单,通过 set follow-fork-mode child | parent 来觉得跟踪 child 还是 parent,然后可以设置断点跟踪了
set follow-fork-mode [程,子进程不受影响。 child: fork 之后调试子进程,父进程不受影响。
因此如果需要调试子进程,在启动 gdb 后:
(gdb) set follow-fork-mode child
Proc2 是 Proc1 的子进程,Proc3 又是 Proc2 的子进程。如何使用 GDB 调试 proc2 或者 proc3 呢? 实际上,GDB 没有对多进程程序调试提供直接支持。例如,使用 GDB 调试某个进程,如果该进程 fork 了子进程,GDB 会继续调试该进程, 子进程会不受干扰地运行下去。如果你事先在子进程代码里设定了断 点,子进程会收到 SIGTRAP 信号并终止。那么该如何调试子进程呢? 其实我们可以利用 GDB 的特点或者其他一些辅助手段来达到目的。此 外,GDB 也在较新内核上加入一些多进程调试支持。
还是上面那个例子,RIM_Oracle_prog fork 出子进程后将紧接着执行 RIM_Oracle_Agent.9i 的二进制代码文件。我们将该文件重命名为 RIM_Oracle_Agent.9i.binary,并新建一个名为 RIM_Oracle_Agent.9i 的 shell 脚本文件,其内容如下:
关于 gdb 调试多进程很早之前就看过,但一直没有总结很深入的学习, 今天又碰到这个问题了,记录下
记得 kk 跟我说过,在开发程序的时候尽量少调试,尽量少使用 gdb 等 调试工具,尽量多的使用 log 等方式来定位错误,这样会大大减少调试 所需的时间和精力,同时也能快速的定位问题。当然,利用 gdb 调试还 是有很多的优势的,比如对于我这个菜鸟来说,可以好好学习下强大的 gdb~ 关于 gdb 的基本调试,基本已经掌握了,经常会使用的一些命令有: s----step n----next c-----continue p----print bt---backtrace b----break 等等
今天查找多进程调试的时候突然注意到 stop 命令,之前一直没有留意, 发现这个命令可以在多进程调试中起到作用
下面描述下多进程的调试
关于 gdb 调试多进程,很经典的一篇文章是 IBM developerworks 上面 的一篇: /developerworks/cn/linux/l-cn-gdbmp/index.html 详细内容见下面描述。
并在子进程代码设置断点。
此外还有 detach-on-fork 参数,指示 GDB 在 fork 之后是否断开(detach) 某个进程的调试,或者都交由 GDB 控制:
set detach-on-fork [on|off]
on: 断开调试 follow-fork-mode 指定的进程。 off: gdb 将控制父进程和子进程。follow-fork-mode 指定的进程
[root@tivf09 root]# pstree -H 6722
通过 pstree 察看进程
启动 GDB,attach 到该进程 用 GDB 连接进程
现在就可以调试了。一个新的问题是,子进程一直在运行,attach 上去 后都不知道运行到哪里了。有没有办法解决呢?
一个办法是,在要调试的子进程初始代码中,比如 main 函数开始处, 加入一段特殊代码,使子进程在某个条件成立时便循环睡眠等待,attach 到进程后在该代码段后设上断点,再把成立的条件取消,使代码可以继 续执行下去。
VNC viewer:输入服务器
输入密码: VNC viewer:输入密码 登录成功,界面和服务器本地桌面上一样:
VNC viewer
下面我们来修改 RIM_Oracle_Agent.9i 脚本,使它看起来像下面这样: #!/bin/sh export DISPLAY=tivf09:1.0; xterm -e gdb RIM_Oracle_Agent.binary 如果你的程序在 exec 的时候还传入了参数,可以改成: #!/bin/sh export DISPLAY=tivf09:1.0; xterm -e gdb --args RIM_Oracle_Agent.binary $@
[root@tivf09 root]#
Vncserver 是一个 Perl 脚本,用来启动 Xvnc(X VNC server)。X client 应用,比如 xterm,VNC viewer 都是和它通信的。如上所示,我们可 以使用的 DISPLAY 值为 tivf09:1。现在就可以从本地机器使用 VNC viewer 连接过去:
New ''tivf09:1 (root)'' desktop is tivf09:1
Starting applications specified in /root/.vnc/xstartup Log file is /root/.vnc/tivf09:1.log
[root@tivf09 root]#
} }
当 attach 到进程后,在该段代码之后设上断点,再把该文件删除就 OK 了。当然你也可以采用其他的条件或形式,只要这个条件可以设置/检 测即可。
Attach 进程方法还是很方便的,它能够应付各种各样复杂的进程系统, 比如孙子/曾孙进程,比如守护进程(daemon process),唯一需要的 就是加入一小段代码。
至于这段代码所采用的条件,看你的偏好了。比如我们可以检查一个指 定的环境变量的值,或者检查一个特定的文件存不存在。以文件为例, 其形式可以如下:
void debug_wait(char *tag_file) {
while(1) {
if (tag_file 存在) 睡眠一段时间;
else break;
attach 方法首先要找到待调试进程的 pid,一般是通过 ps 相关命令,例 如 pstree、ps –aux | grep 进程名称等等,然后通过 attach 关联到相 应的进程。
下面分别是一些介绍文章: GDB 是 linux 系统上常用的 c/c++ 调试工具,功能十分强大。对于较 为复杂的系统,比如多进程系统,如何使用 GDB 调试呢?考虑下面这 个三进程系统: 进程
将被调试,另一个进程置于暂停(suspended)状态。
注意,最好使用 GDB 6.6 或以上版本,如果你使用的是 GDB6.4,就只 有 follow-fork-mode 模式。
follow-fork-mode/detach-on-fork 的使用还是比较简单的,但由于其系 统内核/gdb 版本限制,我们只能在符合要求的系统上才能使用。而且, 由于 follow-fork-mode 的调试必然是从父进程开始的,对于 fork 多次, 以至于出现孙进程或曾孙进程的系统,例如上图 3 进程系统,调试起来 并不方便。
GDB wrapper 很多时候,父进程 fork 出子进程,子进程会紧接着调用 exec 族函数 来执行新的代码。对于这种情况,我们也可以使用 gdb wrapper 方法。 它的优点是不用添加额外代码。
其基本原理是以 gdb 调用待执行代码作为一个新的整体来被 exec 函数 执行,使得待执行代码始终处于 gdb 的控制中,这样我们自然能够调试 该子进程代码。
就会跳出一个终端窗口:
终端
如果你是在一台远程 linux 服务器上调试,那么可以使用 VNC(Virtual Network Computing) viewer 从本地机器连接到服务器上使用 xterm。 在此之前,需要在你的本地机器上安装 VNC viewer,在服务器上安装 并启动 VNC server。大多数 linux 发行版都预装了 vnc-server 软件包, 所以我们可以直接运行 vncserver 命令。注意,第一次运行 vncserver 时会提示输入密码,用作 VNC viewer 从客户端连接时的密码。可以在 VNC server 机器上使用 vncpasswd 命令修改密码。 [root@tivf09 root]# vncserver
nobody 6722 6721 0 05:57 ?