GDB调试实战二启动调试

本文介绍如何使用GDB进行多线程程序调试,包括设置断点、线程切换控制、临时断点使用及智能指针查看等技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

一、线程增加断点

基本的功能有了,可以开始了,首先在发送和接收线程增加断点:

(gdb) b 36
Breakpoint 14 at 0x417e3e: file /root/projects/gdbTest/inet/Server.cpp, line 36.
(gdb) c
Continuing.

Breakpoint 14, inet::Server::__lambda0::operator() (__closure=0xc913c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
(gdb) 

(gdb) b 55
Breakpoint 15 at 0x417fd6: file /root/projects/gdbTest/inet/Server.cpp, line 55.
(gdb) c
Continuing.
[Switching to Thread 0x7f18878d7700 (LWP 4146)]

Breakpoint 15, inet::Server::__lambda1::operator() (__closure=0xc91660) at /root/projects/gdbTest/inet/Server.cpp:55
55                                      int len = pData_->GetMemCount(0);
(gdb) 

通过c命令来启动进程的运行。

(gdb) l
50              {
51                      this->idwork = std::thread([&]() {
52                              //ת53                           while (!quit_)
54                              {
55                                      int len = pData_->GetMemCount(0);
56                                      if (len > 0)
57                                      {
58                                              for (int num = 0; num < len; num++)
59                                              {
(gdb) 
60                                                      std::shared_ptr<global::MemData> tmp = pData_->GetMemData(num, 0);
61                                                      std::cout << "dataparse tmp comData:" << tmp->len << std::endl;
62                                              }
63
64                                      }
65
66                                      len = pData_->GetMemCount(1);
67                                      if (len > 0)
68                                      {
69                                              for (int num = 0; num < len; num++)
(gdb) p tmp
No symbol "tmp" in current context.
(gdb) n
[Switching to Thread 0x7f18880d8700 (LWP 4145)]

Breakpoint 14, inet::Server::__lambda0::operator() (__closure=0xc913c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
(gdb) n
37                                      memmove(dbuf_, barr[num%10], len);
(gdb) p num
$1 = (int &) @0x7ffc47677f9c: 33010
(gdb) p barr
$2 = {0x41cde3 "abce459v,$#@!`pit", 0x41cdf5 "NBG^*(_rrtthth", 0x41ce04 "YT%$#dghhfgdh88980", 0x41ce17 "##$gryryejhetrjrj", 0x41ce29 "whethtwrh8967777", 0x41ce3a "346346546*&****jjkkIO", 
  0x41ce50 "JL)(567568jgjhjgk", 0x41ce62 "ghjgktytuk", 0x41ce6d "45747476466&&***HJJKKTryret", 0x41ce89 "truytritrkmb<>NNHGG$##@"}
(gdb) p /x barr
$3 = {0x41cde3, 0x41cdf5, 0x41ce04, 0x41ce17, 0x41ce29, 0x41ce3a, 0x41ce50, 0x41ce62, 0x41ce6d, 0x41ce89}
(gdb) p /s barr
$4 = {0x41cde3 "abce459v,$#@!`pit", 0x41cdf5 "NBG^*(_rrtthth", 0x41ce04 "YT%$#dghhfgdh88980", 0x41ce17 "##$gryryejhetrjrj", 0x41ce29 "whethtwrh8967777", 0x41ce3a "346346546*&****jjkkIO", 
  0x41ce50 "JL)(567568jgjhjgk", 0x41ce62 "ghjgktytuk", 0x41ce6d "45747476466&&***HJJKKTryret", 0x41ce89 "truytritrkmb<>NNHGG$##@"}
(gdb) p /c barr
$5 = {227 '\343', 245 '\365', 4 '\004', 23 '\027', 41 ')', 58 ':', 80 'P', 98 'b', 109 'm', 137 '\211'}
(gdb) p *barr@3
$7 = {0x41cde3 "abce459v,$#@!`pit", 0x41cdf5 "NBG^*(_rrtthth", 0x41ce04 "YT%$#dghhfgdh88980"}
(gdb) 

上面通过查看数据的命令来查看关心的数据。

二、线程切换控制

在前面看到了线程的切换,下面使用命令锁定一个线程来监控:

(gdb) show scheduler-locking
Mode for locking scheduler during execution is "step".
(gdb) set schedule
schedule-multiple  scheduler-locking  
(gdb) set scheduler-locking on
(gdb) n
37                                      memmove(dbuf_, barr[num%10], len);
(gdb) n
38                                      pData_->ParseComData(dbuf_, len);
(gdb) n
39                                      pData_->ParseNetData(dbuf_, len);
(gdb) n
41                                      num++;
(gdb) n
42                                      sleep(1);
(gdb) n
34                              while (!quit_)
(gdb) n

Breakpoint 1, inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
(gdb) n
37                                      memmove(dbuf_, barr[num%10], len);
(gdb) n
38                                      pData_->ParseComData(dbuf_, len);
(gdb) n
39                                      pData_->ParseNetData(dbuf_, len);
(gdb) n
41                                      num++;
(gdb) 

可以发现,即使在线程Sleep退出时间片占用后,仍然再次回到本线程,而没有跳到另外一个线程中去。这样就很好的解决了多线程,只想对某个线程进行控制的方法。
如果线程很多,可以用命令:

(gdb) info thread
  Id   Target Id         Frame 
* 3    Thread 0x7f5c9d2e3700 (LWP 97767) "gdbTest" inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:41
  2    Thread 0x7f5c9cae2700 (LWP 97768) "gdbTest" 0x00007f5c9d3d3a1d in write () from /lib64/libc.so.6
  1    Thread 0x7f5c9e305740 (LWP 97766) "gdbTest" 0x00007f5c9d6bb017 in pthread_join () from /lib64/libpthread.so.0
(gdb) thread 2

这种方法先进入指定线程,再进行锁定即可。需要说明的是,调试完成后,要记得将线程调度重新设置为off。
如果想达到在IDE软件中对某个变量的不间断的监视,可以使用命令:

(gdb) display num
2: num = (int &) @0x7ffc447985bc: 32883
(gdb) c
Continuing.

Breakpoint 1, inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
2: num = (int &) @0x7ffc447985bc: 32884
(gdb) c
Continuing.
[Switching to Thread 0x7f5c9cae2700 (LWP 97768)]

Breakpoint 2, inet::Server::__lambda1::operator() (__closure=0x6a9660) at /root/projects/gdbTest/inet/Server.cpp:55
55                                      int len = pData_->GetMemCount(0);
1: len = 21
(gdb) c
Continuing.
[Switching to Thread 0x7f5c9d2e3700 (LWP 97767)]

Breakpoint 1, inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
2: num = (int &) @0x7ffc447985bc: 32885
(gdb) c
Continuing.

Breakpoint 1, inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
2: num = (int &) @0x7ffc447985bc: 32886
(gdb) c
Continuing.
[Switching to Thread 0x7f5c9cae2700 (LWP 97768)]

Breakpoint 2, inet::Server::__lambda1::operator() (__closure=0x6a9660) at /root/projects/gdbTest/inet/Server.cpp:55
55                                      int len = pData_->GetMemCount(0);
1: len = 21
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
2:   y  num (cannot be evaluated in the current context)
1:   y  len
(gdb) 

假如对线程中的数据操作达到某个条件感兴趣,可以使用:

(gdb) b 61 if num == 3
Breakpoint 3 at 0x41802a: file /root/projects/gdbTest/inet/Server.cpp, line 61.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000417e3e in inet::Server::__lambda0::operator()() const at /root/projects/gdbTest/inet/Server.cpp:36
        breakpoint already hit 5 times
2       breakpoint     keep y   0x0000000000417fd6 in inet::Server::__lambda1::operator()() const at /root/projects/gdbTest/inet/Server.cpp:55
        breakpoint already hit 3 times
3       breakpoint     keep y   0x000000000041802a in inet::Server::__lambda1::operator()() const at /root/projects/gdbTest/inet/Server.cpp:61
        stop only if num == 3
(gdb) c
Continuing.
[Switching to Thread 0x7f5c9d2e3700 (LWP 97767)]

Breakpoint 1, inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
2: num = (int &) @0x7ffc447985bc: 32887
(gdb) c
Continuing.
[Switching to Thread 0x7f5c9cae2700 (LWP 97768)]

Breakpoint 3, inet::Server::__lambda1::operator() (__closure=0x6a9660) at /root/projects/gdbTest/inet/Server.cpp:61
61                                                      std::cout << "dataparse tmp comData:" << tmp->len << std::endl;
1: len = 36
(gdb) display num
3: num = 3
(gdb) 

三、临时断点的使用

如果只关心一次的情况可以使用临时断点:
先删除原有断点:

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000417e3e in inet::Server::__lambda0::operator()() const at /root/projects/gdbTest/inet/Server.cpp:36
        breakpoint already hit 9 times
2       breakpoint     keep y   0x0000000000417fd6 in inet::Server::__lambda1::operator()() const at /root/projects/gdbTest/inet/Server.cpp:55
        breakpoint already hit 4 times
3       breakpoint     keep y   0x000000000041802a in inet::Server::__lambda1::operator()() const at /root/projects/gdbTest/inet/Server.cpp:61
        stop only if num == 3
        breakpoint already hit 2 times
(gdb) delete 3
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000417e3e in inet::Server::__lambda0::operator()() const at /root/projects/gdbTest/inet/Server.cpp:36
        breakpoint already hit 9 times
2       breakpoint     keep y   0x0000000000417fd6 in inet::Server::__lambda1::operator()() const at /root/projects/gdbTest/inet/Server.cpp:55
        breakpoint already hit 4 times

再重新使用临时断点:

(gdb) tb 61 if num == 3
Temporary breakpoint 4 at 0x41802a: file /root/projects/gdbTest/inet/Server.cpp, line 61.
(gdb) c
Continuing.
[Switching to Thread 0x7f5c9d2e3700 (LWP 97767)]

Breakpoint 1, inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
2: num = (int &) @0x7ffc447985bc: 32891
(gdb) c
Continuing.

Breakpoint 1, inet::Server::__lambda0::operator() (__closure=0x6a93c0) at /root/projects/gdbTest/inet/Server.cpp:36
36                                      int len = strlen(barr[num % 10]);
2: num = (int &) @0x7ffc447985bc: 32892
(gdb) c
2: num = (int &) @0x7ffc447985bc: 32893
(gdb) c
Continuing.
[Switching to Thread 0x7f5c9cae2700 (LWP 97768)]

Temporary breakpoint 4, inet::Server::__lambda1::operator() (__closure=0x6a9660) at /root/projects/gdbTest/inet/Server.cpp:61
61                                                      std::cout << "dataparse tmp comData:" << tmp->len << std::endl;
3: num = 3
1: len = 38
(gdb) 

四、智能指针查看

可以查看一下智能指针的数据内容:

(gdb) n
56                                      if (len > 0)
1: len = 42
(gdb) n
58                                              for (int num = 0; num < len; num++)
3: num = 41
1: len = 42
(gdb) n
60                                                      std::shared_ptr<global::MemData> tmp = pData_->GetMemData(num, 0);
3: num = 0
1: len = 42
(gdb) p tmp
$3 = std::shared_ptr (count 1, weak 0) 0x7f5c98003518
(gdb) p tmp->len
$4 = 60
(gdb) p tmp->buf
$5 = "awhet45747476466&&***HJJKKTryrettruytritrkmb<>NNHGG$##@abce4", '\000' <repeats 39 times>

五、总结

一个初步的GDB实战项目就启动了,灵活的应用各种命令和监控方式,来验证和程序设计本身的目标是否吻合,下一步,就针对具体的数据流程,走一个完整的过程。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值