gdb 笔记(04)— 启用/禁用断点、启用断点一次、查看断点、删除断点、启用断点并命中N次、忽略断点前N次命中)

1. 启用、禁用断点

如果一个断点被禁用,则该断点不会被命中,但是它仍然会在断点列表中显示。我们仍然可以通过 info b 来查看被禁用的断点,也可以通过启用断点命令来重新启用被禁用的断点。

禁用断点的语法如下:

disable   断点编号

启用断点的语法如下:

enable   断点编号

假设我们已经设置了 3 个断点,现在要把 2 号断点暂时禁用,可以使用以下命令来禁用 2 号断点:

disable 2

如果要启用 2 号断点,可以使用以下命令:

enable 2

在禁用断点后,断点的 Enb 标志变成 n ,启用以后又恢复为 y

也可以对一个范围内的断点执行启用或禁用操作,比如禁用编号为 4~10 的断点,则可以使用下述命令:

disable 4-10

启用断点也是一样的。例如要启用编号为 4~10 的断点,则可以使用下述命令:

enable 4-10

示例代码

#include <iostream>
#include <string>

void fun_test(int a, const char *str)
{
    printf("a is %d, str is %s\n", a, str);
}

int add(int a, int b)
{
    return a + b;
}

int main(int argc, char *argv[])
{
    int ret = add(3, 5);
    std::cout << "ret is " << ret << std::endl;
    fun_test(10, "test");
}

示例过程

(gdb) b demo.cpp:6
Breakpoint 1 at 0x969: file demo.cpp, line 6.
(gdb) b demo.cpp:11
Breakpoint 2 at 0x990: file demo.cpp, line 11.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
2       breakpoint     keep y   0x0000000000000990 in add(int, int) 
                                                   at demo.cpp:11
(gdb) disable 2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
2       breakpoint     keep n   0x0000000000000990 in add(int, int) 
                                                   at demo.cpp:11
(gdb) disable 1
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
2       breakpoint     keep n   0x0000000000000990 in add(int, int) 
                                                   at demo.cpp:11
(gdb) enable 1-2
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
2       breakpoint     keep y   0x0000000000000990 in add(int, int) 
                                                   at demo.cpp:11
(gdb) 

2. 启用断点一次

在启用断点时,可以只启用一次,命中一次后会自动禁用,不会再次命中。它与临时断点相似,临时断点只会命中一次,命中一次之后就会自动删除。启用断点一次的不同之处在于断点启用后,虽然只会命中一次,但是不会被删除,而是被禁用。

启用断点一次的语法如下:

enable once 断点编号

比如我们为函数 test_fun 设置了一个断点,然后禁用了该断点。假设该断点编号为 1,如果只启用一次,则可以使用下述命令启用断点一次:

enable once 1

当第一次命中以后,再次调用函数 test_fun 时不会再次被命中,使用 enable once 1 命令后,第一次命中会暂停,后面的调用都不会再次命中。如果此时使用命令 info b 去查看断点信息,会发现 1 号断点的Enb 状态已经变为 n

示例代码:

#include <iostream>
#include <string>

void fun_test(int a, const char *str)
{
    printf("a is %d, str is %s\n", a, str);
}

int main(int argc, char *argv[])
{
    for (int i = 0; i < 10; i++)
    {
        fun_test(10, "test");
    }
}

断点过程:

(gdb) b fun_test
Breakpoint 1 at 0x969: file demo.cpp, line 6.
(gdb) disable 1
(gdb) enable once 1
(gdb) r
Starting program: /home/wohu/cppProject/book_debug/chapter_3.1/demo 
ret is 8

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
[Inferior 1 (process 32327) exited normally]
(gdb) 

3. 启用断点并删除

这同样是启用断点的一种变化用法,即如果断点被启用,当下次命中该断点后,会自动删除。该功能与临时断点相似,相当于把一个被禁用的断点转换为临时断点。语法如下:

enable delete 断点编号

先为函数 fun_test 设置一个断点,并禁用它,然后再启用并删除它,依次执行的命令如下:

b test_fun 
disable 1 
enable delete 1

示例代码如下:

#include <iostream>
#include <string>

void fun_test(int a, const char *str)
{
    printf("a is %d, str is %s\n", a, str);
}

int add(int a, int b)
{
    return a + b;
}

int main(int argc, char *argv[])
{
    int ret = add(3, 5);
    std::cout << "ret is " << ret << std::endl;
    for (int i = 0; i < 10; i++)
    {
        fun_test(10, "test");
    }
}

gdb 中输入 r 执行程序,可以发现 fun_test 中的断点被执行一次,然后自动被删除。

(gdb) b fun_test
Breakpoint 1 at 0x969: file demo.cpp, line 6.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) disable 1
(gdb) enable delete 1
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     del  y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) r
Starting program: /home/wohu/cppProject/book_debug/chapter_3.1/demo 
ret is 8

Temporary breakpoint 1, fun_test (a=10, str=0x555555554b21 "test")
    at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
[Inferior 1 (process 8103) exited normally]
(gdb) 

4. 启用断点并命中N次

这也是启用断点的一种变化用法,即启用断点后可以命中 N 次,但是命中 N 次后,该断点就会被自动禁用,不会再次命中。语法如下:

enable count 数量 断点编号

如果想重新启用已经禁用的断点,并命中 5 次,那么可以使用以下命令:

enable count 5 1

仍然以 fun_test 函数断点为例。先为 fun_test 设置断点,然后禁用,最后以再次启用并命中 5 次的方式启用该断点。在命中 5 次之后,该断点就会被禁用,如图所示,断点命中了 5 次(可以看到输入了 5 次c)以后自动被禁用,从最后的提示信息也可以看到,1 号断点已经命中了 5 次。

(gdb) b fun_test
Breakpoint 1 at 0x969: file demo.cpp, line 6.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) disable 1
(gdb) enable count 5 1
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     dis  y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
	disable after next 5 hits
(gdb) r
Starting program: /home/wohu/cppProject/book_debug/chapter_3.1/demo 
ret is 8

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
[Inferior 1 (process 8285) exited normally]
(gdb) 

5. 忽略断点前N次命中

与条件断点类似,即在设置断点时可以指定接下来的 N 次命中都忽略,直到第 N+1 次命中时运行才暂停。语法如下:

ignore 断点编号 次数

例如我们为函数 fun_test 设置了断点,但是因为 fun_test 可能被多次调用,所以我们希望在第 8 次被调用时能够命中,前 7次的调用都被忽略,则使用以下命令:

ignore 1 7

这样在执行代码时,前 7 次对函数 fun_test 的调用都会被忽略,不会命中断点,但是从第 8 次调用开始都会命中,如下所示:

(gdb) b fun_test
Breakpoint 1 at 0x969: file demo.cpp, line 6.
(gdb) ignore 1 7 
Will ignore next 7 crossings of breakpoint 1.
(gdb) r
Starting program: /home/wohu/cppProject/book_debug/chapter_3.1/demo 
ret is 8
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test
a is 10, str is test

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test

Breakpoint 1, fun_test (a=10, str=0x555555554b21 "test") at demo.cpp:6
6	    printf("a is %d, str is %s\n", a, str);
(gdb) c
Continuing.
a is 10, str is test
[Inferior 1 (process 8593) exited normally]
(gdb) 

6. 查看断点

查看断点可以通过下列命令实现:

info breakpoints 
info break 
info b 
i b

上述命令只有第一个比较长,后面的 3 个都是简化缩写形式,所有的命令执行结果都是相同的,如下所示。

(gdb) b fun_test
Breakpoint 1 at 0x969: file demo.cpp, line 6.
(gdb) info breakpoint
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6

也可以只查看某一个具体的断点,方法为在这些命令后面加上断点编号,

(gdb) info breakpoints 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) info breakpoint  1
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) info break 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) info b 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) i b 1
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000969 in fun_test(int, char const*) at demo.cpp:6
(gdb) 

查看断点信息的命令由 infobreakpoint 两个命令组合而成,这两个命令有多种组合方式。

  • info 可以写为两种形式:infoi
  • breakpoint 可以写为 3 种形式:breakpointbreakb

因此,一共有 6 种组合形式,例如, i breakpoint 也是查看断点的有效命令。

7. 删除断点

删除断点主要有两个相关的命令,即 cleardelete

7.1 删除所有断点

gdb 中输入以下命令就会删除所有的断点

delete

在删除之前会有确认对话框,询问是否删除所有断点。如果选择 y ,则删除所有断点,否则不会执行任何操作。

(gdb) b demo.cpp:10
Breakpoint 1 at 0x990: file demo.cpp, line 10.
(gdb) b demo.cpp:12
Breakpoint 2 at 0x998: file demo.cpp, line 12.
(gdb) b demo.cpp:14
Breakpoint 3 at 0x9a9: file demo.cpp, line 14.
(gdb) delete
Delete all breakpoints? (y or n) y

7.2 删除指定断点

delete 断点编号

比如要删除 5 号断点,可以在 gdb 中输入以下命令:

delete 5

如果要同时删除编号为 5 和 6 的两个断点,可以使用以下命令:

delete 5 6

7.3 删除指定范围的断点

delete 范围

如果要删除编号为 5~7 的断点,则可以使用以下命令:

delete 5-7

还可以删除多个范围的断点,比如要删除编号为 5-710-12 的断点,则可以使用以下命令:

delete 5-7 10-12

7.4 删除指定函数的断点

clear 函数名

比如要删除 test_fun 函数断点,可以执行以下命令:

clear test_fun

这会删除所有的 test_fun 函数断点。如果有多个同名函数断点,这些同名函数断点都会被删除。

7.5 删除指定行号的断点

clear 行号

比如要删除 demo.cpp 第 10 行的断点,可以使用命令:

clear demo.cpp:10

也可以简写为

clear 10

删除断点命令 cleardelete 是有区别的。

  • delete 命令是全局的,不受栈帧的影响;
  • clear 命令受到当前栈帧的制约,删除的是将要执行的下一处指令的断点;
  • delete 命令可以删除所有断点,包括观察点和捕获点等;
  • clear 命令不能删除观察点和捕获点;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wohu007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值