停下来环顾程序

转自  http://blog.csdn.net/todd911/article/details/28091389

1.断点列表

创建的每个断点(包括断电、监视点和捕获点)都标识为从1开始的唯一整数标识符。这个标识符用来执行该断点上的各种

操作。调试器还包含一种列出所有断点及其属性的方法。

调试下面的代码:(代码1)

[cpp] view plaincopy

  1. #include <stdio.h>
  2. void display(int i)
  3. {
  4. i = i + 1;
  5. printf("i = %d\n",i);
  6. }
  7. int main(void)
  8. {
  9. int i = 1;
  10. display(i);
  11. return 0;
  12. }

设置断点--显示断点列表--删除断点--显示删除后断点列表:

(gdb) break main
Breakpoint 1 at 0x80483d4: file a.c, line 11.
(gdb) break display
Breakpoint 2 at 0x80483aa: file a.c, line 5.
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080483d4 in main at a.c:11
2       breakpoint     keep y   0x080483aa in display at a.c:5
(gdb) delete 1
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x080483aa in display at a.c:5
(gdb)

info breakpoints命令的简写为i b

2.设置断点

GDB中有许多指定断点的方式,下面是一些常见的方法。持久断点使用break命令(简写为b)

以下使用代码1调试:

在函数的入口处设置断点:

(gdb) break main
Breakpoint 1 at 0x80483d4: file a.c, line 11.

在当前活动源代码文件的某行设置断点:

(gdb) break 11
Breakpoint 3 at 0x80483d4: file a.c, line 11.

在某文件的某行处设置断点:

(gdb) break a.c:11
Note: breakpoint 3 also set at pc 0x80483d4.
Breakpoint 4 at 0x80483d4: file a.c, line 11.

在某文件的某函数入口处设置断点:

(gdb) break a.c:main
Breakpoint 6 at 0x80483d4: file a.c, line 11.

当设置一个断点时,该断点的有效性会持续到删除,禁用或退出GDB时,而临时断点在首次到达后就会被自动删除的断点。

临时断点使用tbreak命令(简写为tb)设置。它与break的用法相同。

2.断点的持久性

如果我们在修改和重新编译代码时没有退出GDB,那么下次在执行GDB的run命令时,GDB会感知到代码已修改,并重新

加载新版本:

以下使用代码1调试:

在A窗口执行如下:

(gdb) b main
Breakpoint 1 at 0x80483d4: file a.c, line 11.

(gdb)

在B窗口执行如下:

修改display函数中的

i = i + 1;

i = i + 2;

并重新进行编译

回到A窗口继续执行:

(gdb) r

Breakpoint 1, main () at a.c:11
11              int i = 1;

(gdb) n
12              display(i);
(gdb) s
display (i=1) at a.c:5
5               i = i + 2;

发现已经是修改后的代码。

3.删除断点

以下使用代码1调试:

删除指定断点

(gdb) info breakpoints
Num     Type           Disp Enb Address    What
4       breakpoint     keep y   0x080483d4 in main at a.c:11
5       breakpoint     keep y   0x080483aa in display at a.c:5
(gdb) delete 4
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
5       breakpoint     keep y   0x080483aa in display at a.c:5
(gdb)

删除所有断点

(gdb) info breakpoints
Num     Type           Disp Enb Address    What
5       breakpoint     keep y   0x080483aa in display at a.c:5
6       breakpoint     keep y   0x080483d4 in main at a.c:11
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb)

其中delete命令的简写为d。

如果clear不带任何参数,则删除当前停止的断点:

(gdb) info breakpoints
Num     Type           Disp Enb Address    What
17      breakpoint     dis  y   0x080483d4 in main at a.c:11
19      breakpoint     keep y   0x080483aa in display at a.c:5
(gdb) r
Starting program: /root/a.out
Breakpoint 17, main () at a.c:11
11              int i = 1;
(gdb) clear
Deleted breakpoint 17
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
19      breakpoint     keep y   0x080483aa in display at a.c:5

如果clear带参数,则删除所在行的所有断点。gdb允许在同一行设置多个断点,如果使用delete,必须一个一个删除,而clear

可以一起删除。

可以使用如下任何一种方式:

clear function、clear filename:function、clear line_number和clear file:linenumber

(gdb) info breakpoints
Num     Type           Disp Enb Address    What
14      breakpoint     keep y   0x080483d4 in main at a.c:11
15      breakpoint     keep y   0x080483d4 in main at a.c:11
16      breakpoint     keep y   0x080483d4 in main at a.c:11
(gdb) clear main
Deleted breakpoints 14 15 16
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb)

4.禁用断点

每个断点都可以被禁用或启用。只有当GDB遇到启用断点时才会暂停程序的执行;否则会忽略禁用的断点。

使用disable breakpoint-list命令禁用断点,使用enable breakpoint-list命令启用断点。

以下使用代码1调试:

(gdb) info breakpoints
Num     Type           Disp Enb Address    What
17      breakpoint     keep y   0x080483d4 in main at a.c:11
18      breakpoint     keep y   0x080483aa in display at a.c:5
(gdb) disable 17
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
17      breakpoint     keep n   0x080483d4 in main at a.c:11
18      breakpoint     keep y   0x080483aa in display at a.c:5
(gdb) enable 17
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
17      breakpoint     keep y   0x080483d4 in main at a.c:11
18      breakpoint     keep y   0x080483aa in display at a.c:5
(gdb)

还有一个enable once命令,在断点下次引起GDB暂停执行后被禁用,语法如下:

enable once breakpoint-list

对于下面的代码进行调试:(代码2)

[cpp] view plaincopy

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int m = 1;
  5. int i;
  6. for (i=0; i<10; i++) {
  7. printf("%d",i);
  8. }
  9. return 0;
  10. }

(gdb) b 8
Breakpoint 2 at 0x80483c5: file b.c, line 8.
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x080483c5 in main at b.c:8
(gdb) disable 2
(gdb) enable once 2
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
2       breakpoint     dis  y   0x080483c5 in main at b.c:8
(gdb) r
Starting program: /root/a.out
Breakpoint 2, main () at b.c:8
8                       printf("%d\n",i);
(gdb) c
Continuing.
0123456789
Program exited normally.

断点只执行了执行了一次,后面的断点被忽略。

没有disable once 命令。

5.断点属性

可以使用info breakpoints(简写为 i b)命令来获取设置的所有断点的清单以及它们的属性。

(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080483d4 in main at a.c:11
2       breakpoint     keep y   0x080483aa in display at a.c:5

下面说明下i b的输出。

Num:标识符,断点的唯一标识符。

Type:类型,这个字段之处该断点是断点、监视点还是捕获点。

Disp:部署,每个断电都有一个部署,只是断点下次引起GDB暂停程序的执行后该断点上会发生什么事情。可能的部署有

一下3种。

keep:保持,下次达到断点后不改变断点。这时新建断点后的默认部署。

del:删除,下次达到断点后删除该断点。使用rbreak命令会出现该部署。

dis:禁用,下次达到断点时会禁用该断点。使用enable once命令会出现该部署。

Enb:启用状态,说明断点当前是启用还是禁用的。

Address:这时内存中设置断点的位置。

what:位置,显示了断点所在位置的行号和文件名。

6.恢复执行

恢复执行的方法有3类,第一类是使用step和next但不调试程序,仅执行代码的下一行然后再次暂停。第二类由使用continue

组成,使GDB无条件恢复程序的执行,直到它遇到另一个断电或者程序结束。最后一类方法涉及条件:用finish或until命令恢复。

这种情况下,GDB恢复执行;程序继续运行直到遇到某个预先确定的条件,到达另一个断点或者程序完成。

step(简写为s)、next(简写为n)和continue(简写为c)比较简单,不详细说明。有一点需要注意,next和step都采用一个可选的

数值参数,表示使用next或者step执行的额外行数,比如next 3在一行中键入next三次。

6.1.finish

finish(简写为fin)指示GDB恢复执行,直到敲好在当前栈帧完成之后为止,也就是说,如果你在一个不是main的函数中,finish

命令会导致GDB恢复执行,直到恰好在函数返回之后为止。

以下使用代码1调试:

(gdb) b display 
Breakpoint 1 at 0x4004ff: file gdb.c, line 5.
(gdb) r
Starting program: /home/yanwenjie/ctest/a.out

Breakpoint 1, display (i=1) at gdb.c:5
5        i = i + 1;
(gdb) finish
Run till exit from #0  display (i=1) at gdb.c:5
i = 2
main () at gdb.c:13
13        return 0;
(gdb)

6.2.until

until(简写为u)会执行循环的其余部分,让GDB在循环后面的第一行代码处暂停,条件时循环中不能有断点。

使用代码2进行调试:

(gdb) b main

(gdb) r
Breakpoint 1, main () at gdb.c:5
5        int m = 1;
(gdb) n
7        for (i=0; i<10; i++) {
(gdb) 
8 printf("%d",i);
(gdb) 
7        for (i=0; i<10; i++) {
(gdb) until
10        return 0;
(gdb) n
11 }

7.条件断点

条件断点告诉调试器只有当符合某种条件时才在断点处停止,比如当变量具有某个特定的感兴趣的值时。

设置条件断点的语法为:

break break-args if (condition)

条件终端极其灵活,主要包含如下运算符:

1.相等、逻辑或不相等运算符(<、<=、==、!=、>、>= 、&&、||等),例如:

break 180 if string == NULL && i < 0

2.按位和移位运算符(&、|、^、>>、<<等),例如:

break test.c:34 if(x & y) == 1

3.算术运算符(+、-、x、/、%),例如:

break myfunc if i % (j+3) != 0

4.你自己的函数,只要它们被链接到程序中,例如:

break test.c:myfunc if ! check_variable(i)

5.库函数,只要该库被链接到代码中,例如:

break 44 if stelen(mystring) == 0

8.断点命令列表

当gdb遇到断点时,几乎总是要查看某个变量,如果反复遇到同一个断点,将反复查看相同的变量,让GDB在每次到达某个断点时

自动执行一组命令,从而完成一个过程,这就是断点命令列表可以完成的事情。

使用commands命令设置命令列表。

commands命令设置命令列表。

commands breakpoint-num

.....

commands

....

end

其中breakpoint-number是要将命令添加到其上的断点的标识符。commands是用新行分割任何有效gdb命令列表。逐条输入命令,

然后键入end表示输入命令完毕。从那以后,每当gdb在这个断点处中断时,它会执行你输入的任何命令。

使用代码2进行调试:

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040050c in main at gdb.c:8
(gdb) commands 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>printf "i is %d\n",i
>end
(gdb) r
Breakpoint 1, main () at gdb.c:8
8 printf("%d",i);
i is 0
(gdb) c
Continuing.

Breakpoint 1, main () at gdb.c:8
8 printf("%d",i);
i is 1

9.监视点

监视点是一种特殊类型的断点,它类似与正常断点,是要求GDB暂停程序执行的指令。监视点指示gdb每当某个表达式改变了

值就暂停执行。当变量i存在作用域中时,使用如下方法设置监视点:

watch i

它会使得每次i改变时gdb暂停。

使用如下代码调试:

[cpp] view plaincopy

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int m = 1;
  5. int i;
  6. for (i=0; i<10; i++) {
  7. if (i%2 ==0) {
  8. m++;
  9. }
  10. }
  11. return 0;
  12. }

调试结果如下:

(gdb) b main
Breakpoint 1 at 0x4004b8: file gdb.c, line 5.
(gdb) r
Breakpoint 1, main () at gdb.c:5
5        int m = 1;
(gdb) watch m
Hardware watchpoint 2: m
(gdb) p m
$1 = 0
(gdb) c
Continuing.
Hardware watchpoint 2: m

Old value = 0  
New value = 2

(好像对m的赋值没有作为监控点而停住)
main () at gdb.c:7
7        for (i=0; i<10; i++) {
(gdb) p m
$2 = 2

时间: 2025-01-02 09:19:28

停下来环顾程序的相关文章

《软件调试的艺术》笔记--停下来环顾程序

1.断点列表 创建的每个断点(包括断电.监视点和捕获点)都标识为从1开始的唯一整数标识符.这个标识符用来执行该断点上的各种 操作.调试器还包含一种列出所有断点及其属性的方法. 调试下面的代码:(代码1) #include <stdio.h> void display(int i) { i = i + 1; printf("i = %d\n",i); } int main(void) { int i = 1; display(i); return 0; } 设置断点--显示断

利用GDB对程序进行调试

第一章初涉调试会话 调试工具 GDB Unix下最常用的调试工具 DDD 基于GUI的调试器,大多数工具都是GDB的GUI前端. Eclipse IDE也是一种调试工具 atoi( )把字符串变为整数,头文件是include<stdlib.h> gcc -g -Wall -o insert_sort ins.c -g选项可以让编译器将符号表(对应于程序的变量和代码行的内存地址列表)保存在生成的可执行文件里中. 这样才能在调试会话的过程中引用源代码中的变量和行号,比如"在第30行停止&

《软件调试的艺术The Art of Debugging with GDB,DDD,and Eclipse》

#第1章 **使用TUI模式的GDB**指定-tui或者CTRL+X+A #第2章 停下来环顾程序# **断点**通知GDB暂停程序的执行 **监视点**通知GDB当特定内存位置(或者涉及一个或多个位置的表达式)的值发生变化时暂停执行. **捕获点**通知GDB当特定事件发生时暂停执行. ###2.4.1在GDB中设置断点### ●break *function* ●break *line_number* ●break *filename:function* ●break *filename:l

《软件调试的艺术》学习笔记——GDB使用技巧摘要

<软件调试的艺术>学习笔记——GDB使用技巧摘要 <软件调试的艺术>,因为名是The Art of Debugging with GDB, DDD, and Eclipse. 作者是美国的Norman Matloff和Peter Jay Salzman,中文版由张云翻译.是人邮出版社图灵程序设计丛书初版.这里称为"艺术",个人觉得有点过了,但是其中关于gdb以及在gdb基础之上集成的DDD和Eclipse调试技巧的整理确实是做的很好,对于Linux/开源社区下的

[转] 一个优秀的程序员应该如何提高工作效率?

转自:http://www.cnblogs.com/cherry0327/p/5395957.html 当我们评价一个程序员是否优秀时,要从多个方面进行评估. 专业技能.专业知识.创造力.经验,这些都是重要的因素.当然,还有他们的工作态度.工作效率和工作质量.如果程序员的工作是没有效率的,那就意味着他们所投入的时间和精力是没有效果的.在livecoding.tv最近发布的一篇博文中,他们总结了10个影响程序员工作效率的坏习惯.看完这篇文章后你会发现,里面所列举的坏习惯,总有一两个可以在自己的身上

gcc编译c语言

摘自<Linux程序设计>第四版,人民邮电出版社 c语言程序的编译与调试<<使用gcc编译,gdb调试>> 程序编译过程:词法分析-->语法分析-->中间代码生成-->代码优化-->目标代码生成gcc编译器:预处理(preprocessing)-->编译(compilation)-->汇编(assembly)-->连接(link) 文件后缀名说明:.c:c语言代码.a:由目标文件构成的库文件.C,.cc,.cpp:C++代码.h

王家林谈Spark性能优化第四季!

内容: 1.序列化: 2.JVM性能调优: ==========Spark性能调优之序列化============ 1.之所以进行序列化,最重要的原因是:内存空间有限(减少GC的压力,最大化避免Full GC的产生,一旦产生Full GC,则整个Task则处于停止状态).减少磁盘IO的压力.减少网络IO的压力: 2.什么时候会必要的产生序列化和反序列化呢?发生磁盘IO和网络通信的时候会发生序列化和反序列化,更为重要的考虑序列化和反序列化的时候有另外两种情况: 1)Persist(Checkpoi

HDU4445CrazyTank高中物理知识忘得差不多了

丘芈洪 嫩潘斜 荇砺荏病 西垒壁战场上殚精竭虑的徐骁显然要更早接触到圣旨所以当他的大军连夜火速退至妃子 矫瞽硎 武当山也不回了那么你师父师伯们岂不是得气得吐血." 始终撑伞为轩辕青锋遮挡风雨的徐凤年握紧伞柄阴沉道:"肯定是那叫赵黄巢的古怪道人 汉颂宜任张叭厍着貉笔笆戳悼僖說 方丈们也不知道把寺庙修缮修缮她家好歹是佛门第一圣地听名头就知道不比天师府小啊 卖炭老翁察觉到异样吁了一声拉住老牛停下炭车十指冻疮裂血的年幼稚童跳下马车 璞バ臁 碱厣凋饴 盔搴梃 嚎笪散扼 才有了京城白衣案

关于recv的返回值

通常recv有几种返回值 1.==0 表示收到FIN包, 因为FIN包,是状态为标记为FIN的空包,没有携带数据,所以recv的长度为0 2.>0 表示收到了数据, 但是有没有收完,是不知道的 3.<0 1) == EAGAIN  表示接收缓冲区中已经没数据了,需要暂停下,业务程序需要检查下包的完整性,才知道有没有收完,如果没收完,就继续recv 2) != EAGAIN  表示接收出错了,如果是服务端, 就可以直接关闭连接了. 切记收到FIN包后,准备关闭连接前,一定要处理完接收缓冲区中的数