一、线程增加断点
基本的功能有了,可以开始了,首先在发送和接收线程增加断点:
(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实战项目就启动了,灵活的应用各种命令和监控方式,来验证和程序设计本身的目标是否吻合,下一步,就针对具体的数据流程,走一个完整的过程。