gdb怎样设置当程序产生新线程的时候暂停?

gdb怎样设置当程序产生新线程的时候暂停?,第1张

以下面的代码为例:

void *sample_run(void *arg)

{

for () {

}

return NULL

}

int main(int argc, char* argv[])

{

// suppress warnings

(void)argc(void)argv

pthread_t thdid = 0

pthread_create(&thdid, NULL, sample_run, NULL)

printf("Hello World!\n")

for () {

}

return 0

}

编译出的粗信可执行程序假定为hello,

那么在命令行输入gdb hello

输入 b pthread_create

再输入r,可以看到程序暂停在pthread_create,

然后再输入b sample_run,输入c,可以看到程岩此轮序进一步暂停在sample_run。

输入bt,可以看到调用栈。

请采纳扒首,谢谢!

下面的有两个C文件。(并没有bug。我们使用gdb来查看程序运行的细节)

程序的一个为test.c,其中有主程序main()。mean.c程序中定义了mean()函数,并在main()中调用。

test.c

#define ARRAYSIZE 4

float mean(float, float)

int main()

{

int i

float a=4.5

float b=5.5

float rlt=0.0

float array_a[ARRAYSIZE]={1.0, 2.0, 3.0, 4.0}

float array_b[ARRAYSIZE]={4.0, 3.0, 2.0, 1.0}

float array_rlt[ARRAYSIZE]

for(i = 0i <ARRAYSIZE - 1i++) {

array_rlt[i] = mean(array_a[i], array_b[i])

}

rlt = mean(a, b)

return 0

}

mean.c

float mean(float a, float b)

{

return (a + b)/2.0

}

使用gcc同时编译上面两个程序。为了使用gdb对进行调试,必须使用-g选项(在编译时生成debugging信息):

$gcc -g -o test test.c mean.c

生成main可执行文件。

(如有必要,使用:

$chmod +x test

来增加用户的执行权限。)

进入gdb,准备调试程序:

$gdb test

进入gdb的互动命令行。

显示程序

我们可以直接显示某一行的程序,比如查看第9行程序:

(gdb) list 9

将显示以第9行为中心,总共10行的程序。我们实际上编译了两个文件,在没有说明的情况下,默认为主程序文件test.c:

4

5int main()

6{

7int i

8float a=4.5

9float b=5.5

10float rlt=0.0

11

12float array_a[ARRAYSIZE]={1.0, 2.0, 3.0, 4.0}

13float array_b[ARRAYSIZE]={4.0, 3.0, 2.0, 1.0}

如果要查看mean.c中的内容,需要说明文件名:

(gdb) list mean.c:1

可以具体说明所要列出的程序行的范围:

(gdb) list 5, 15

即显示5-15行的程序。

显示某个函数,比如:

(gdb) list mean

设置断点

我们可以运行程序:

(gdb) run

程序正常结束。

运行程序并没有什么有趣的地方。gdb的主要功能在于能让程序在中途暂停。

断点(break point)是程序执行中的一个位置。在gdb中,当程序运行到该位置时,程序会暂停,我们可以查看此时的程序状况,比如变量的值。

我们可以在程序的某一行设置断点,比如:

(gdb) break 16

将在test.c的第16行设置断点。

你慧脊可以查看自己设置的断点:

(gdb) info break

每个断点有一个识别序号。我们可以根据序号删除某个断点:

(gdb) delete 1

也可以删除所兄伏有断点:

(gdb) delete breakpoints

查看断点

设置断点,并使用run运行程序,程序将运行到16行时暂停。gdb显示:

Breakpoint 1, main () at test.c:16

16for(i = 0i <ARRAYSIZE - 1i++) {

查看断点所在行:

(gdb) list

查看断点处的某个变量值:

(gdb) print a

(gdb) print array_a

查看所有的局部变量:

(gdb) info local

查看此时的栈状态 (反映了函数调用,羡碧携见Linux从程序到进程):

(gdb) info stack

可以更改变量的值。

(gdb) set var a=0.0

(gdb) set var array_a={0.0, 0.0, 1.0, 1.0}

当程序继续运行时,将使用更改后的值。

如果我们将断点设置在:

(gdb) break mean.c:2

此时栈中有两个a,一个属于main(),一个属于mean()。我们可以用function::variable的方式区分:

(gdb) print mean::a

一、GDB 概述

GDB 是 GNU 开源组织发布的一个强大的 UNIX 下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像 VC 、 BCB 等 IDE 的调试,但如果你是在 UNIX 平台下做软件,你会发现 GDB 这个调试工具有比 VC 、 BCB 的图形化调试器更强大的功能。所谓 “ 寸有所长,尺有所短 ” 就是这个道理。

一般来说, GDB 主要帮忙你完滑卜成下面四个方面的功能:

1 、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。

2 、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)

3 、当程序被停住时,可以检查此时你的程序中所发生的事。

4 、动态卜让运的改变你程序的执行环境。

从上面看来, GDB 和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现 GDB 这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。

二、一个调试示例

源程序: tst.c

[cpp] view plain copy

#include <stdio.h>

int func(int n)

{

int sum=0,i

for(i=0i<ni++)

{

sum+=i

}

return sum

}

int main()

{

int i

long result = 0

for(i=1i<=100i++)

{

result += i

}

printf("result[1-100] = %d /n", result )

printf("result[1-250] = %d /n", func(250) )

}

编译生成执行文件:( Linux 下)

hchen/test>cc -g tst.c -o tst

启动Gdb:

以上是对于gdb的感性认识,接下来系统地认识一下 gdb 吧。型梁

三、使用 GDB

1.基础

一般来说 GDB 主要调试的是 C/C++ 的程序。要调试 C/C++ 的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器( cc/gcc/g++ )的 -g 参数可以做到这一点。如:

>cc -g hello.c -o hello

>g++ -g hello.cpp -o hello

如果没有 -g ,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用 -g 把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用 gdb 来调试他。

启动 gdb 后,就你被带入 gdb 的调试环境中,就可以使用 gdb 的命令开始调试程序了, gdb 的命令可以使用 help 命令来查看,

gdb 的命令很多, gdb 把之分成许多个种类。 help 命令只是例出 gdb 的命令种类,如果要看种类中的命令,可以使用 help <class>命令,如: help breakpoints ,查看设置断点的所有命令。也可以直接 help <command>来查看命令的帮助。如下图所示:

要退出 gdb 时,只用发 quit 或命令简称 q 就行了。

2 GDB 中运行 UNIX 的 shell 程序

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

shell <command string>

调用 UNIX 的 shell 来执行 <command string>,环境变量 SHELL 中定义的 UNIX 的 shell 将会被用来执行 <command string>,如果 SHELL 没有定义,那就使用 UNIX 的标准 shell : /bin/sh 。(在 Windows 中使用 Command.com 或 cmd.exe )

还有一个 gdb 命令是 make :

make <make-args>

可以在 gdb 中执行 make 命令来重新 build 自己的程序。这个命令等价于 “ shell make <make-args>”

3 在 GDB 中运行程序

在 gdb 中,运行程序使用 r 或是 run 命令。程序的运行,你有可能需要设置下面四方面的事。

1 、程序运行参数。

set args 可指定运行时参数。(如: set args 10 20 30 40 50 )

show args 命令可以查看设置好的运行参数。

2 、运行环境。

path <dir>可设定程序的运行路径。

show paths 查看程序的运行路径。

set environment varname [=value] 设置环境变量。如: set env USER=hchen

show environment [varname] 查看环境变量。

3 、工作目录。

cd <dir>相当于 shell 的 cd 命令。

pwd 显示当前的所在目录。

4 、程序的输入输出。

info terminal 显示你程序用到的终端的模式。

使用重定向控制程序输出。如: run >outfile

tty 命令可以指写输入输出的终端设备。如: tty /dev/ttyb

4 调试程序

调试程序中,暂停程序运行是必须的, GDB 可以方便地暂停程序的运行。你可以设置程序的在哪行停住,在什么条件下停住,在收到什么信号时停往等等。以便于你查看运行时的变量,以及运行时的流程。

在 gdb 中,我们可以有以下几种暂停方式:

断点( BreakPoint )、

观察点( WatchPoint )、

捕捉点( CatchPoint )、

信号( Signals )、

线程停止( Thread Stops )。

如果要恢复程序运行,可以使用 c 或是 continue 命令。

一、设置断点( BreakPoint )

我们用 break 命令来设置断点。正面有几点设置断点的方法:

break <function>

在进入指定函数时停住。 C++ 中可以使用 class::function 或 function(type,type) 格式来指定函数名。

break <linenum>

在指定行号停住。

break +offset

break -offset

在当前行号的前面或后面的 offset 行停住。 offiset 为自然数。

break filename:linenum

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

break filename:function

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

break *address

在程序运行的内存地址处停住。

break

break 命令没有参数时,表示在下一条指令处停住。

break ... if <condition>

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

查看断点时,可使用 info 命令,如下所示:(注: n 表示断点号)

info breakpoints [n]

info break [n]

二、设置观察点( WatchPoint )

观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点:

watch <expr>

为表达式(变量) expr 设置一个观察点。一量表达式值有变化时,马上停住程序。

rwatch <expr>

当表达式(变量) expr 被读时,停住程序。

awatch <expr>

当表达式(变量)的值被读或被写时,停住程序。

info watchpoints

列出当前所设置了的所有观察点。

三、设置捕捉点( CatchPoint )

你可设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是 C++ 的异常。设置捕捉点的格式为:

catch <event>

当 event 发生时,停住程序。 event 可以是下面的内容:

1 、 throw 一个 C++ 抛出的异常。( throw 为关键字)

2 、 catch 一个 C++ 捕捉到的异常。( catch 为关键字)

3 、 exec 调用系统调用 exec 时。( exec 为关键字,目前此功能只在 HP-UX 下有用)

4 、 fork 调用系统调用 fork 时。( fork 为关键字,目前此功能只在 HP-UX 下有用)

5 、 vfork 调用系统调用 vfork 时。( vfork 为关键字,目前此功能只在 HP-UX 下有用)

6 、 load 或 load <libname>载入共享库(动态链接库)时。( load 为关键字,目前此功能只在 HP-UX 下有用)

7 、 unload 或 unload <libname>卸载共享库(动态链接库)时。( unload 为关键字,目前此功能只在 HP-UX 下有用)

tcatch <event>

只设置一次捕捉点,当程序停住以后,应点被自动删除。

四、维护停止点

上面说了如何设置程序的停止点, GDB 中的停止点也就是上述的三类。在 GDB 中,如果你觉得已定义好的停止点没有用了,你可以使用 delete 、 clear 、 disable 、 enable 这几个命令来进行维护。

clear

清除所有的已定义的停止点。

clear <function>

clear <filename:function>

清除所有设置在函数上的停止点。

clear <linenum>

clear <filename:linenum>

清除所有设置在指定行上的停止点。

delete [breakpoints] [range...]

删除指定的断点, breakpoints 为断点号。如果不指定断点号,则表示删除所有的断点。 range 表示断点号的范围(如: 3-7 )。其简写命令为 d 。

比删除更好的一种方法是 disable 停止点, disable 了的停止点, GDB 不会删除,当你还需要时, enable 即可,就好像回收站一样。

disable [breakpoints] [range...]

disable 所指定的停止点, breakpoints 为停止点号。如果什么都不指定,表示 disable 所有的停止点。简写命令是 dis.

enable [breakpoints] [range...]

enable 所指定的停止点, breakpoints 为停止点号。

enable [breakpoints] once range...

enable 所指定的停止点一次,当程序停止后,该停止点马上被 GDB 自动 disable 。

enable [breakpoints] delete range...

enable 所指定的停止点一次,当程序停止后,该停止点马上被 GDB 自动删除。

五、停止条件维护

前面在说到设置断点时,我们提到过可以设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能,这里,我想专门说说这个条件的相关维护命令。一般来说,为断点设置一个条件,我们使用 if 关键词,后面跟其断点条件。并且,条件设置好后,我们可以用 condition 命令来修改断点的条件。(只有 break 和 watch 命令支持 if , catch 目前暂不支持 if )

condition <bnum><expression>

修改断点号为 bnum 的停止条件为 expression 。

condition <bnum>

清除断点号为 bnum 的停止条件。

还有一个比较特殊的维护命令 ignore ,你可以指定程序运行时,忽略停止条件几次。

ignore <bnum><count>

表示忽略断点号为 bnum 的停止条件 count 次。

六、为停止点设定运行命令

我们可以使用 GDB 提供的 command 命令来设置停止点的运行命令。也就是说,当运行的程序在被停止住时,我们可以让其自动运行一些别的命令,这很有利行自动化调试。对基于 GDB 的自动化调试是一个强大的支持。

commands [bnum]

... command-list ...

end

为断点号 bnum 指写一个命令列表。当程序被该断点停住时, gdb 会依次运行命令列表中的命令。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12374155.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存