1. 程式人生 > 其它 >GDB除錯實戰二啟動除錯

GDB除錯實戰二啟動除錯

技術標籤:C++gdb

一、執行緒增加斷點

基本的功能有了,可以開始了,首先在傳送和接收執行緒增加斷點:

(gdb)b36
Breakpoint14at0x417e3e:file/root/projects/gdbTest/inet/Server.cpp,line36.
(gdb)c
Continuing.

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

(gdb)b55
Breakpoint15at0x417fd6:file/root/projects/gdbTest/inet/Server.cpp,line55.
(gdb)c
Continuing.
[SwitchingtoThread0x7f18878d7700(LWP4146)]

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

通過c命令來啟動程序的執行。

(gdb)l
50{
51this->idwork=std::thread([&](){
52//ת53while(!quit_)
54{
55intlen=pData_->GetMemCount(0);
56if(len>0)
57{
58for(intnum=0;num<len;num++)
59{
(gdb)
60std::shared_ptr<global::MemData>tmp=pData_->GetMemData(num,0);
61std::cout<<"dataparsetmpcomData:"<<tmp->len<<std::endl;
62}
63
64}
65
66len=pData_->GetMemCount(1);
67if(len>0)
68{
69for(intnum=0;num<len;num++)
(gdb)ptmp
Nosymbol"tmp"incurrentcontext.
(gdb)n
[SwitchingtoThread0x7f18880d8700(LWP4145)]

Breakpoint14,inet::Server::__lambda0::operator()(__closure=0xc913c0)at/root/projects/gdbTest/inet/Server.cpp:36
36intlen=strlen(barr[num%10]);
(gdb)n
37memmove(dbuf_,barr[num%10],len);
(gdb)pnum
$1=(int&)@0x7ffc47677f9c:33010
(gdb)pbarr
$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/xbarr
$3={0x41cde3,0x41cdf5,0x41ce04,0x41ce17,0x41ce29,0x41ce3a,0x41ce50,0x41ce62,0x41ce6d,0x41ce89}
(gdb)p/sbarr
$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/cbarr
$5={227'\343',245'\365',4'\004',23'\027',41')',58':',80'P',98'b',109'm',137'\211'}
(gdb)p*
[email protected]
$7={0x41cde3"abce459v,$#@!`pit",0x41cdf5"NBG^*(_rrtthth",0x41ce04"YT%$#dghhfgdh88980"} (gdb)

上面通過檢視資料的命令來檢視關心的資料。

二、執行緒切換控制

在前面看到了執行緒的切換,下面使用命令鎖定一個執行緒來監控:

(gdb)showscheduler-locking
Modeforlockingschedulerduringexecutionis"step".
(gdb)setschedule
schedule-multiplescheduler-locking
(gdb)setscheduler-lockingon
(gdb)n
37memmove(dbuf_,barr[num%10],len);
(gdb)n
38pData_->ParseComData(dbuf_,len);
(gdb)n
39pData_->ParseNetData(dbuf_,len);
(gdb)n
41num++;
(gdb)n
42sleep(1);
(gdb)n
34while(!quit_)
(gdb)n

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

可以發現,即使線上程Sleep退出時間片佔用後,仍然再次回到本執行緒,而沒有跳到另外一個執行緒中去。這樣就很好的解決了多執行緒,只想對某個執行緒進行控制的方法。
如果執行緒很多,可以用命令:

(gdb)infothread
IdTargetIdFrame
*3Thread0x7f5c9d2e3700(LWP97767)"gdbTest"inet::Server::__lambda0::operator()(__closure=0x6a93c0)at/root/projects/gdbTest/inet/Server.cpp:41
2Thread0x7f5c9cae2700(LWP97768)"gdbTest"0x00007f5c9d3d3a1dinwrite()from/lib64/libc.so.6
1Thread0x7f5c9e305740(LWP97766)"gdbTest"0x00007f5c9d6bb017inpthread_join()from/lib64/libpthread.so.0
(gdb)thread2

這種方法先進入指定執行緒,再進行鎖定即可。需要說明的是,除錯完成後,要記得將執行緒排程重新設定為off。
如果想達到在IDE軟體中對某個變數的不間斷的監視,可以使用命令:

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

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

Breakpoint2,inet::Server::__lambda1::operator()(__closure=0x6a9660)at/root/projects/gdbTest/inet/Server.cpp:55
55intlen=pData_->GetMemCount(0);
1:len=21
(gdb)c
Continuing.
[SwitchingtoThread0x7f5c9d2e3700(LWP97767)]

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

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

Breakpoint2,inet::Server::__lambda1::operator()(__closure=0x6a9660)at/root/projects/gdbTest/inet/Server.cpp:55
55intlen=pData_->GetMemCount(0);
1:len=21
(gdb)infodisplay
Auto-displayexpressionsnowineffect:
NumEnbExpression
2:ynum(cannotbeevaluatedinthecurrentcontext)
1:ylen
(gdb)

假如對執行緒中的資料操作達到某個條件感興趣,可以使用:

(gdb)b61ifnum==3
Breakpoint3at0x41802a:file/root/projects/gdbTest/inet/Server.cpp,line61.
(gdb)infob
NumTypeDispEnbAddressWhat
1breakpointkeepy0x0000000000417e3eininet::Server::__lambda0::operator()()constat/root/projects/gdbTest/inet/Server.cpp:36
breakpointalreadyhit5times
2breakpointkeepy0x0000000000417fd6ininet::Server::__lambda1::operator()()constat/root/projects/gdbTest/inet/Server.cpp:55
breakpointalreadyhit3times
3breakpointkeepy0x000000000041802aininet::Server::__lambda1::operator()()constat/root/projects/gdbTest/inet/Server.cpp:61
stoponlyifnum==3
(gdb)c
Continuing.
[SwitchingtoThread0x7f5c9d2e3700(LWP97767)]

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

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

三、臨時斷點的使用

如果只關心一次的情況可以使用臨時斷點:
先刪除原有斷點:

(gdb)infob
NumTypeDispEnbAddressWhat
1breakpointkeepy0x0000000000417e3eininet::Server::__lambda0::operator()()constat/root/projects/gdbTest/inet/Server.cpp:36
breakpointalreadyhit9times
2breakpointkeepy0x0000000000417fd6ininet::Server::__lambda1::operator()()constat/root/projects/gdbTest/inet/Server.cpp:55
breakpointalreadyhit4times
3breakpointkeepy0x000000000041802aininet::Server::__lambda1::operator()()constat/root/projects/gdbTest/inet/Server.cpp:61
stoponlyifnum==3
breakpointalreadyhit2times
(gdb)delete3
(gdb)infob
NumTypeDispEnbAddressWhat
1breakpointkeepy0x0000000000417e3eininet::Server::__lambda0::operator()()constat/root/projects/gdbTest/inet/Server.cpp:36
breakpointalreadyhit9times
2breakpointkeepy0x0000000000417fd6ininet::Server::__lambda1::operator()()constat/root/projects/gdbTest/inet/Server.cpp:55
breakpointalreadyhit4times

再重新使用臨時斷點:

(gdb)tb61ifnum==3
Temporarybreakpoint4at0x41802a:file/root/projects/gdbTest/inet/Server.cpp,line61.
(gdb)c
Continuing.
[SwitchingtoThread0x7f5c9d2e3700(LWP97767)]

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

Breakpoint1,inet::Server::__lambda0::operator()(__closure=0x6a93c0)at/root/projects/gdbTest/inet/Server.cpp:36
36intlen=strlen(barr[num%10]);
2:num=(int&)@0x7ffc447985bc:32892
(gdb)c
2:num=(int&)@0x7ffc447985bc:32893
(gdb)c
Continuing.
[SwitchingtoThread0x7f5c9cae2700(LWP97768)]

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

四、智慧指標檢視

可以檢視一下智慧指標的資料內容:

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

五、總結

一個初步的GDB實戰專案就啟動了,靈活的應用各種命令和監控方式,來驗證和程式設計本身的目標是否吻合,下一步,就針對具體的資料流程,走一個完整的過程。