1. 程式人生 > 其它 >GDB除錯實戰一基礎準備

GDB除錯實戰一基礎準備

技術標籤:C++C++11gdb

一、GDB應用

在前面講過了很多GDB的命令和相關的除錯小程式,但是好多人發現在學習完成這些命令後,不知道如何應用到實際的工程中去,這裡就使用一個實際的工程進行一下除錯。為了合乎規範,使用的並不是完整和全面的公司的程式碼,而在上面進行了縮減了的程式碼,但整體的架構幾乎一致,完全可以和實際工程比擬。

二、基本情況介紹

1、伺服器軟硬體
伺服器使用的是2*64=128核心的DELL伺服器,記憶體128G,SSH遠端登陸。CentOS7的作業系統。

2、編譯工具

使用cmake3.3 ,gcc-g++ 4.8.5

3、除錯工具

使用gdb-7.6除錯。

4、程式碼結構

三、啟動除錯前的準備

這個程式是一個網路服務端的高併發的簡化,為了簡單並沒有把epoll弄進來,而是通過兩個執行緒模擬傳送和接收,並送到邏輯處理佇列進行整包控制來進行。
先看一下崩潰轉儲的設定:

[[email protected]build]#ulimit-c
10240

如果為0的話,請使用:
ulimit -c N 設定大小,N單位為k。
上面的設定只適合當前終端,退出後變為0
永久修改:

/etc/profile:全域性
.bash_profile:當前使用者
ulimit-cN
source.bash_profile

設定這個引數的目的是為了在除錯時如果程序崩潰,可以產生轉儲檔案Core。

寫一個簡單的CMakeLists.txt,然後放到當前的根目錄下,建立一個資料夾build,然後進入到這個資料夾:

cdbuild
cmake..
make

就會在此目錄下生成可執行檔案,以後所有的操作都是以這個資料夾為基本目錄操作的,請知悉。

四、啟動程序

然後啟動程序:

[[email protected]build]#ls
CMakeCache.txtCMakeFilescmake_install.cmakecore.70236gdbTestMakefile
[[email protected]build]#nohup./gdbTest>1.log2>&1&
[1]4144

這個4144是啟動的程序ID,和ps -ef|grep gdbTest得到的ID一樣。如果不是使用上面的方法啟動程序,可以使用這個命令來得到當前的程序ID,效果一樣。然後使用tail命令來檢視程式的正常輸出。

[[email protected]build]#ls
1.logCMakeCache.txtCMakeFilescmake_install.cmakecore.70236gdbTestMakefile
[[email protected]build]#tail-f-n201.log
dataparsetmpnetData:100
dataparsetmpnetData:100
dataparsetmpnetData:100
dataparsetmpnetData:100
dataparsetmpcomData:60
dataparsetmpcomData:60

這裡將使用動態載入已執行的程序的方式來除錯:

[[email protected]build]#ls
1.logCMakeCache.txtCMakeFilescmake_install.cmakecore.70236gdbTestMakefile
[[email protected]build]#gdbattach4144(注意:除錯完成要detach)
GNUgdb(GDB)RedHatEnterpriseLinux7.6.1-120.el7
Copyright(C)2013FreeSoftwareFoundation,Inc.
LicenseGPLv3+:GNUGPLversion3orlater<http://gnu.org/licenses/gpl.html>
Thisisfreesoftware:youarefreetochangeandredistributeit.
ThereisNOWARRANTY,totheextentpermittedbylaw.Type"showcopying"
and"showwarranty"fordetails.
ThisGDBwasconfiguredas"x86_64-redhat-linux-gnu".
Forbugreportinginstructions,pleasesee:
<http://www.gnu.org/software/gdb/bugs/>...
attach:Nosuchfileordirectory.
Attachingtoprocess4144
Readingsymbolsfrom/root/projects/gdbTest/build/gdbTest...done.
Readingsymbolsfrom/lib64/libstdc++.so.6...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib64/libstdc++.so.6
Readingsymbolsfrom/lib64/libm.so.6...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib64/libm.so.6
Readingsymbolsfrom/lib64/libgcc_s.so.1...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib64/libgcc_s.so.1
Readingsymbolsfrom/lib64/libpthread.so.0...(nodebuggingsymbolsfound)...done.
[NewLWP4146]
[NewLWP4145]
[Threaddebuggingusinglibthread_dbenabled]
Usinghostlibthread_dblibrary"/lib64/libthread_db.so.1".
Loadedsymbolsfor/lib64/libpthread.so.0
Readingsymbolsfrom/lib64/libc.so.6...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib64/libc.so.6
Readingsymbolsfrom/lib64/ld-linux-x86-64.so.2...(nodebuggingsymbolsfound)...done.
Loadedsymbolsfor/lib64/ld-linux-x86-64.so.2
0x00007f18884b0017inpthread_join()from/lib64/libpthread.so.0
Missingseparatedebuginfos,use:debuginfo-installglibc-2.17-317.el7.x86_64libgcc-4.8.5-44.el7.x86_64libstdc++-4.8.5-44.el7.x86_64
(gdb)stop
(gdb)

此處需要root許可權,如果沒有則會報許可權受限,sudo或者其它可以取得root方式均可。啟動後使用stop命令停止當前程序 。

執行一下list命令,檢視當前可以看到的程式碼,發現並沒匯入的程式碼

(gdb)l
1#include<cstdio>
2#include"ModuleNet.h"
3
4intmain()
5{
6ModuleNetmn;
7std::stringip="192.168.0.2";
8mn.Init(0,ip);
9mn.Start(0);
10getchar();
(gdb)

如果想檢視當前路徑,需要加上shell表示是執行的shell命令:

(gdb)shellls
1.logCMakeCache.txtCMakeFilescmake_install.cmakecore.70236gdbTestMakefile
(gdb)

如果想除錯哪個路徑下的檔案,可以使用下面的命令:

(gdb)dir../inet/
Sourcedirectoriessearched:/root/projects/gdbTest/build/../inet:$cdir:$cwd
(gdb)

匯入想要除錯的檔案路徑。

(gdb)lServer.cpp:18
13Server::~Server()
14{
15this->id.join();
16this->idwork.join();
17}
18intServer::InitServer(intcount,std::string&ip)
19{
20if(nullptr==this->pData_)
21{
22this->pData_=std::make_shared<data::IData>();
(gdb)

如果沒有前面的 dir命令,則無法進行檢視。

(gdb)showdir
Sourcedirectoriessearched:/root/projects/gdbTest/build/../inet:$cdir:$cwd
(gdb)

使用:號可以連線匯入多個路徑

(gdb)dir../inet/:../data/netdata/:../data/comdata/
Sourcedirectoriessearched:
/root/projects/gdbTest/build/../inet:/root/projects/gdbTest/build/../data/netdata:/root/projects/gdbTest/build/../data/comdata:$cdir:$cwd
(gdb)

這樣就可以在關心的檔案中進行各種操作如下斷點。假使不希望再使用當前的匯入路徑的檔案可以直接使用dir命令,則當前所有的匯入都會清除,只留下預設部分。

(gdb)dir
Reinitializesourcepathtoempty?(yorn)y
Sourcedirectoriessearched:$cdir:$cwd

準備好上述的基本的環境後,可以下斷點了。斷點設定方法在前面的GDB應用中介紹過,下面使用其中的方法來進行斷點操作。
如果想在函式中下斷點,但又不太清楚的記得函式名稱可以用名空間名稱-類名等依次向下點選兩次TAB鍵,則會自動出現相關的符號:

(gdb)binet::Server
Server
Server::InitServer(int,std::string&)
Server::RunWork()
Server::RunWork()::{lambda()#1}&&std::forward<inet::Server::RunWork()::{lambda()#1}>(std::remove_reference<inet::Server::RunWork()::{lambda()#1}>::type&)
Server::RunWork()::{lambda()#1}::operator()()const
Server::Server()
Server::Start()
Server::Start()::{lambda()#1}&&std::forward<inet::Server::Start()::{lambda()#1}>(std::remove_reference<inet::Server::Start()::{lambda()#1}>::type&)
Server::Start()::{lambda()#1}::operator()()const
Server::Stop()
Server::~Server()

如果進一步指定一個函式的開頭字母:

(gdb)binet::Server::S
Server()
Start()
Start()::{lambda()#1}&&std::forward<inet::Server::Start()::{lambda()#1}>(std::remove_reference<inet::Server::Start()::{lambda()#1}>::type&)
Start()::{lambda()#1}::operator()()const
Stop()

當然,還是習慣於用行號來下斷點:

(gdb)lServer.cpp:33
28}
29intServer::Start()
30{
31intnum=0;
32this->id=std::thread([&](){
33//
34while(!quit_)
35{
36intlen=strlen(barr[num%10]);
37memmove(dbuf_,barr[num%10],len);
(gdb)bServer.cpp:36
Breakpoint1at0x417e3e:file/root/projects/gdbTest/inet/Server.cpp,line36.
(gdb)

可以對斷點進行檢視和刪除:

(gdb)infob
NumTypeDispEnbAddressWhat
2breakpointkeepy0x0000000000417e3eininet::Server::__lambda0::operator()()constat/root/projects/gdbTest/inet/Server.cpp:36
(gdb)delete2
(gdb)infob
Nobreakpointsorwatchpoints.
(gdb)bServer.cpp:36
Breakpoint3at0x417e3e:file/root/projects/gdbTest/inet/Server.cpp,line36.
(gdb)delete
Deleteallbreakpoints?(yorn)y
(gdb)

還可以對斷點進行禁用、啟用和忽略:

(gdb)binet::Server::Start
Breakpoint4at0x417f64:file/root/projects/gdbTest/inet/Server.cpp,line31.
(gdb)clear
Nosourcefilespecified.
(gdb)infob
NumTypeDispEnbAddressWhat
4breakpointkeepy0x0000000000417f64ininet::Server::Start()at/root/projects/gdbTest/inet/Server.cpp:31
(gdb)disable4
(gdb)infob
NumTypeDispEnbAddressWhat
4breakpointkeepn0x0000000000417f64ininet::Server::Start()at/root/projects/gdbTest/inet/Server.cpp:31
(gdb)enable
(gdb)infob
NumTypeDispEnbAddressWhat
4breakpointkeepy0x0000000000417f64ininet::Server::Start()at/root/projects/gdbTest/inet/Server.cpp:31
(gdb)in
inferiorinfoinit-if-undefinedinterpreter-execinterrupt
(gdb)ignore4
Secondargument(specifiedignore-count)ismissing.
(gdb)infob
NumTypeDispEnbAddressWhat
4breakpointkeepy0x0000000000417f64ininet::Server::Start()at/root/projects/gdbTest/inet/Server.cpp:31
(gdb)

同樣,使用clear也可以刪除斷點,clear Server.cpp:31 就會把上面的斷點4給刪除。需要注意的是,clear這個命令是基於行命令刪除的(也就是說基於行號)。

檢視一下當前的執行緒:

(gdb)infothread
IdTargetIdFrame
3Thread0x7f18880d8700(LWP4145)"gdbTest"0x00007f188819e85dinnanosleep()from/lib64/libc.so.6
2Thread0x7f18878d7700(LWP4146)"gdbTest"0x00007f188819e85dinnanosleep()from/lib64/libc.so.6
*1Thread0x7f18890fa740(LWP4144)"gdbTest"0x00007f18884b0017inpthread_join()from/lib64/libpthread.so.0

檢視當前所有執行緒的堆疊資訊:

(gdb)threadapplyallbt

Thread3(Thread0x7f18880d8700(LWP4145)):
#00x00007f188819e85dinnanosleep()from/lib64/libc.so.6
#10x00007f188819e6f4insleep()from/lib64/libc.so.6
#20x0000000000417f3bininet::Server::__lambda0::operator()(__closure=0xc913c0)at/root/projects/gdbTest/inet/Server.cpp:42
#30x0000000000419e96instd::_Bind_simple<inet::Server::Start()::__lambda0()>::_M_invoke<>(std::_Index_tuple<>)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1732
#40x0000000000419d45instd::_Bind_simple<inet::Server::Start()::__lambda0()>::operator()(void)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1720
#50x0000000000419c76instd::thread::_Impl<std::_Bind_simple<inet::Server::Start()::__lambda0()>>::_M_run(void)(this=0xc913a8)at/usr/include/c++/4.8.2/thread:115
#60x00007f1888c90330in??()from/lib64/libstdc++.so.6
#70x00007f18884aeea5instart_thread()from/lib64/libpthread.so.0
#80x00007f18881d796dinclone()from/lib64/libc.so.6

Thread2(Thread0x7f18878d7700(LWP4146)):
#00x00007f188819e85dinnanosleep()from/lib64/libc.so.6
#10x00007f188819e6f4insleep()from/lib64/libc.so.6
#20x0000000000418122ininet::Server::__lambda1::operator()(__closure=0xc91660)at/root/projects/gdbTest/inet/Server.cpp:77
#30x0000000000419e38instd::_Bind_simple<inet::Server::RunWork()::__lambda1()>::_M_invoke<>(std::_Index_tuple<>)(this=0xc91660)at/usr/include/c++/4.8.2/functional:1732
#40x0000000000419d27instd::_Bind_simple<inet::Server::RunWork()::__lambda1()>::operator()(void)(this=0xc91660)at/usr/include/c++/4.8.2/functional:1720
#50x0000000000419c58instd::thread::_Impl<std::_Bind_simple<inet::Server::RunWork()::__lambda1()>>::_M_run(void)(this=0xc91648)at/usr/include/c++/4.8.2/thread:115
#60x00007f1888c90330in??()from/lib64/libstdc++.so.6
#70x00007f18884aeea5instart_thread()from/lib64/libpthread.so.0
#80x00007f18881d796dinclone()from/lib64/libc.so.6

Thread1(Thread0x7f18890fa740(LWP4144)):
#00x00007f18884b0017inpthread_join()from/lib64/libpthread.so.0
#10x00007f1888c900f7instd::thread::join()()from/lib64/libstdc++.so.6
#20x0000000000417d36ininet::Server::~Server(this=0xc8f058,__in_chrg=<optimizedout>)at/root/projects/gdbTest/inet/Server.cpp:15
#30x000000000041c9a4in__gnu_cxx::new_allocator<inet::Server>::destroy<inet::Server>(this=0xc8f050,__p=0xc8f058)at/usr/include/c++/4.8.2/ext/new_allocator.h:124
#40x000000000041c961instd::allocator_traits<std::allocator<inet::Server>>::_S_destroy<inet::Server>(__a=...,__p=0xc8f058)at/usr/include/c++/4.8.2/bits/alloc_traits.h:281
#50x000000000041c917instd::allocator_traits<std::allocator<inet::Server>>::destroy<inet::Server>(__a=...,__p=0xc8f058)at/usr/include/c++/4.8.2/bits/alloc_traits.h:405
#60x000000000041c85finstd::_Sp_counted_ptr_inplace<inet::Server,std::allocator<inet::Server>,(__gnu_cxx::_Lock_policy)2>::_M_dispose(this=0xc8f040)
at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:407
#70x0000000000415aeainstd::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release(this=0xc8f040)at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:144
#80x0000000000415639instd::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count(this=0x7ffc47678008,__in_chrg=<optimizedout>)at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:546
#90x000000000041bf24instd::__shared_ptr<inet::Server,(__gnu_cxx::_Lock_policy)2>::~__shared_ptr(this=0xaf7e47678000,__in_chrg=<optimizedout>)at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:781
#100x000000000041bf62instd::shared_ptr<inet::Server>::~shared_ptr(this=0x7ffc47678000,__in_chrg=<optimizedout>)at/usr/include/c++/4.8.2/bits/shared_ptr.h:93
#110x000000000041be28inModuleNet::~ModuleNet(this=0x7ffc47678000,__in_chrg=<optimizedout>)at/root/projects/gdbTest/ModuleNet.cpp:8
#120x000000000041bd11inmain()at/root/projects/gdbTest/main.cpp:12

進一步檢視一下當前執行緒除錯排程鎖的情況,並通過設定引數進行鎖定和放開:

(gdb)showscheduler-locking
Modeforlockingschedulerduringexecutionis"step".
(gdb)setscheduler-lockingon
(gdb)showscheduler-locking
Modeforlockingschedulerduringexecutionis"on".
(gdb)setscheduler-lockingoff
(gdb)showscheduler-locking
Modeforlockingschedulerduringexecutionis"off".

通過這個命令,可以強制指定只調試某個執行緒,當初第一次用這個命令時,還忽視了,結果發現另外一個執行緒死活也進不了斷點。初學者不要忘記不用了改回到初始狀態。
檢視一下當前執行緒的幀和相關堆疊:

(gdb)infoframe
Stacklevel0,frameat0x7ffc47677ea0:
rip=0x7f18884b0017inpthread_join;savedrip0x7f1888c900f7
calledbyframeat0x7ffc47677eb0
Arglistat0x7ffc47677e38,args:
Localsat0x7ffc47677e38,Previousframe'sspis0x7ffc47677ea0
Savedregisters:
rbxat0x7ffc47677e68,rbpat0x7ffc47677e70,r12at0x7ffc47677e78,r13at0x7ffc47677e80,r14at0x7ffc47677e88,r15at0x7ffc47677e90,ripat0x7ffc47677e98
(gdb)bt
#00x00007f18884b0017inpthread_join()from/lib64/libpthread.so.0
#10x00007f1888c900f7instd::thread::join()()from/lib64/libstdc++.so.6
#20x0000000000417d36ininet::Server::~Server(this=0xc8f058,__in_chrg=<optimizedout>)at/root/projects/gdbTest/inet/Server.cpp:15
#30x000000000041c9a4in__gnu_cxx::new_allocator<inet::Server>::destroy<inet::Server>(this=0xc8f050,__p=0xc8f058)at/usr/include/c++/4.8.2/ext/new_allocator.h:124
#40x000000000041c961instd::allocator_traits<std::allocator<inet::Server>>::_S_destroy<inet::Server>(__a=...,__p=0xc8f058)at/usr/include/c++/4.8.2/bits/alloc_traits.h:281
#50x000000000041c917instd::allocator_traits<std::allocator<inet::Server>>::destroy<inet::Server>(__a=...,__p=0xc8f058)at/usr/include/c++/4.8.2/bits/alloc_traits.h:405
#60x000000000041c85finstd::_Sp_counted_ptr_inplace<inet::Server,std::allocator<inet::Server>,(__gnu_cxx::_Lock_policy)2>::_M_dispose(this=0xc8f040)
at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:407
#70x0000000000415aeainstd::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release(this=0xc8f040)at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:144
#80x0000000000415639instd::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count(this=0x7ffc47678008,__in_chrg=<optimizedout>)at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:546
#90x000000000041bf24instd::__shared_ptr<inet::Server,(__gnu_cxx::_Lock_policy)2>::~__shared_ptr(this=0xaf7e47678000,__in_chrg=<optimizedout>)at/usr/include/c++/4.8.2/bits/shared_ptr_base.h:781
#100x000000000041bf62instd::shared_ptr<inet::Server>::~shared_ptr(this=0x7ffc47678000,__in_chrg=<optimizedout>)at/usr/include/c++/4.8.2/bits/shared_ptr.h:93
#110x000000000041be28inModuleNet::~ModuleNet(this=0x7ffc47678000,__in_chrg=<optimizedout>)at/root/projects/gdbTest/ModuleNet.cpp:8
#120x000000000041bd11inmain()at/root/projects/gdbTest/main.cpp:12
(gdb)

如果想進入某個執行緒並檢視相關堆疊和具體的資訊:

(gdb)thread3
[Switchingtothread3(Thread0x7f18880d8700(LWP4145))]
#00x00007f188819e85dinnanosleep()from/lib64/libc.so.6
(gdb)bt
#00x00007f188819e85dinnanosleep()from/lib64/libc.so.6
#10x00007f188819e6f4insleep()from/lib64/libc.so.6
#20x0000000000417f3bininet::Server::__lambda0::operator()(__closure=0xc913c0)at/root/projects/gdbTest/inet/Server.cpp:42
#30x0000000000419e96instd::_Bind_simple<inet::Server::Start()::__lambda0()>::_M_invoke<>(std::_Index_tuple<>)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1732
#40x0000000000419d45instd::_Bind_simple<inet::Server::Start()::__lambda0()>::operator()(void)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1720
#50x0000000000419c76instd::thread::_Impl<std::_Bind_simple<inet::Server::Start()::__lambda0()>>::_M_run(void)(this=0xc913a8)at/usr/include/c++/4.8.2/thread:115
#60x00007f1888c90330in??()from/lib64/libstdc++.so.6
#70x00007f18884aeea5instart_thread()from/lib64/libpthread.so.0
#80x00007f18881d796dinclone()from/lib64/libc.so.6
(gdb)bt
#00x00007f188819e85dinnanosleep()from/lib64/libc.so.6
#10x00007f188819e6f4insleep()from/lib64/libc.so.6
#20x0000000000417f3bininet::Server::__lambda0::operator()(__closure=0xc913c0)at/root/projects/gdbTest/inet/Server.cpp:42
#30x0000000000419e96instd::_Bind_simple<inet::Server::Start()::__lambda0()>::_M_invoke<>(std::_Index_tuple<>)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1732
#40x0000000000419d45instd::_Bind_simple<inet::Server::Start()::__lambda0()>::operator()(void)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1720
#50x0000000000419c76instd::thread::_Impl<std::_Bind_simple<inet::Server::Start()::__lambda0()>>::_M_run(void)(this=0xc913a8)at/usr/include/c++/4.8.2/thread:115
#60x00007f1888c90330in??()from/lib64/libstdc++.so.6
#70x00007f18884aeea5instart_thread()from/lib64/libpthread.so.0
#80x00007f18881d796dinclone()from/lib64/libc.so.6
(gdb)infoframe
Stacklevel0,frameat0x7f18880d7c70:
rip=0x7f188819e85dinnanosleep;savedrip0x7f188819e6f4
calledbyframeat0x7f18880d7e50
Arglistat0x7f18880d7c58,args:
Localsat0x7f18880d7c58,Previousframe'sspis0x7f18880d7c70
Savedregisters:
ripat0x7f18880d7c68
(gdb)bt
#00x00007f188819e85dinnanosleep()from/lib64/libc.so.6
#10x00007f188819e6f4insleep()from/lib64/libc.so.6
#20x0000000000417f3bininet::Server::__lambda0::operator()(__closure=0xc913c0)at/root/projects/gdbTest/inet/Server.cpp:42
#30x0000000000419e96instd::_Bind_simple<inet::Server::Start()::__lambda0()>::_M_invoke<>(std::_Index_tuple<>)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1732
#40x0000000000419d45instd::_Bind_simple<inet::Server::Start()::__lambda0()>::operator()(void)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1720
#50x0000000000419c76instd::thread::_Impl<std::_Bind_simple<inet::Server::Start()::__lambda0()>>::_M_run(void)(this=0xc913a8)at/usr/include/c++/4.8.2/thread:115
#60x00007f1888c90330in??()from/lib64/libstdc++.so.6
#70x00007f18884aeea5instart_thread()from/lib64/libpthread.so.0
#80x00007f18881d796dinclone()from/lib64/libc.so.6

棧幀可以自由的在範圍內上下選擇:

(gdb)up1
#10x00007f188819e6f4insleep()from/lib64/libc.so.6
(gdb)up2
#30x0000000000419e96instd::_Bind_simple<inet::Server::Start()::__lambda0()>::_M_invoke<>(std::_Index_tuple<>)(this=0xc913c0)at/usr/include/c++/4.8.2/functional:1732
1732std::forward<_Args>(std::get<_Indices+1>(_M_bound))...);
(gdb)down1
#20x0000000000417f3bininet::Server::__lambda0::operator()(__closure=0xc913c0)at/root/projects/gdbTest/inet/Server.cpp:42
42sleep(1);
(gdb)

怎麼樣?這些基礎命令的使用在實際的工程中發現它的更具體的用法了吧。

五、總結

GDB的使用非常靈活和強大,需要把相關文件中的知識和實際的應用不斷的結合,才能形成自己的一套除錯技巧和除錯思想。工具誰都會用,但是怎麼才能用好,更能為我所用,這才是根本。