日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

软件调试的艺术笔记:GDB

發布時間:2023/11/27 生活经验 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 软件调试的艺术笔记:GDB 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

很久之前,在https://blog.csdn.net/fengbingchun/article/details/41413381中簡單整理過gdb中常用的一些命令,不齊全,這里按照《軟件調試的藝術》一書中關于gdb的介紹再做次整理?!盾浖{試的藝術》于2009年由人民郵電出版社出版。

1. 預備知識

GDB:Unix程序員最常用的調試工具,是由Richard Stallman開發的GNU項目調試器(GNU Project Debugger)。

DDD:Data Display Debugger,數據顯示調試器,GDB的GUI(圖形用戶界面)前端:用戶通過GUI發出命令,GUI將這些命令傳遞給GDB。

Eclipse:IDE(集成開發環境)。

GDB的命令允許在不產生歧義的情況下使用縮寫

從版本6.1以來,GDB已經以名為TUI(Terminal User Interface, 終端用戶界面)的模式提供了基于文本交互和圖形用戶交互之間的折中方法。在這一模式中,GDB將終端屏幕劃分為類似于DDD的源文本窗口和控制臺的多個子窗口:可以在類似于源文本窗口的子窗口中跟蹤程序執行的進展過程,同時在類似于控制臺的子窗口中發出GDB命令。也可以使用另一個程序CGDB,該程序也提供了類似的功能。

為了以TUI模式運行GDB,可以在調用GDB時在命令行上指定-tui選型,如gdb -tui main,或者處于非TUI模式時在GDB中使用Ctrl+X+A組合鍵。如果當前處于TUI模式,后一種命令方式就會使你離開TUI模式。TUI模式中,GDB窗口劃分為兩個子窗口:一個用于輸入GDB命令,而另一個用于查看源代碼。需要注意的是,在一些情況下TUI可能不能按照用戶所需要的方式運作。

1.5 主要調試器操作

單步調試源代碼:

(1).斷點:調試工具會在指定斷點處暫停程序的執行,在GDB中是通過break命令及其行號完成的。

(2).單步調試:GDB的next命令讓GDB執行下一行,然后暫停。step命令的作用與此類似,只是在函數調用時step命令會進入函數,而next導致程序執行的暫停出現在下次調用函數時。

(3).恢復操作:在GDB中,continue命令通知調試器恢復執行并繼續,直到遇到斷點為止。

(4).臨時斷點:在GDB中,tbreak命令與break相似,但是這一命令設置的斷點的有效期限只到首次到達指定行時為止。GDB中還有創建特殊類型的一次性斷點的命令until和finish。

檢查變量:當調試器暫停了程序的執行后,可以執行一些命令來顯示程序變量的值。這些變量可以是局部變量、全局變量、數組的元素和C語言的struct、C++類中的成員變量等。如果發現某個變量有一個出乎意料的值,那往往是找出某個程序錯誤的位置和性質的重要線索。最基本的變量顯示類型是僅僅輸出當前值。在GDB中使用print命令輸出當前值,如查看變量j的當前值執行”(gdb) print j”。

設置監視點以應對變量值的改變:監視點結合了斷點和變量檢查的概念。最基本形式的監視點通知調試器,每當指定變量的值發生變化時都暫停程序的執行。例如,在程序執行期間,假設要在變量z改變值時查看程序的狀態,在GDB中,可以執行如下命令:”(gdb) watch z”,當運行程序時,每當z的值發生變化,GDB都會暫停執行。更好的方法是,可以基于條件表達式來設置監視點。例如,假設要查找程序執行期間z的值大于28的第一個位置,在GDB中,輸入”(gdb) watch (z>28)”。監視點對局部變量的用途一般沒有對作用域更寬的變量的用途大,因為一旦變量超出作用域(即當在其中定義變量的函數結束時),在局部變量上設置的監視點就會被取消。

上下移動調用棧:在函數調用期間,與調用關聯的運行時信息存儲在稱為棧幀(stack frame)的內存區域中。幀中包含函數的局部變量的值、其形參,以及調用該函數的位置的記錄。每次發生函數調用時,都會創建一個新幀,并將其推到一個系統維護的棧上;棧最上方的幀表示當前正在執行的函數,當函數退出時,這個幀被彈出棧,并且被釋放。在GDB中可用用如下命令查看以前的幀:“(gdb) frame 1”。當執行GDB的frame命令時,當前正在執行的函數的幀被編號為0,其父幀(即該函數的調用者的棧幀)被編號為1,父幀的父幀被編號為2,以此類推。GDB的up命令將你帶到調用棧中的下一個父幀(例如,從幀0到幀1),down則引向相反反向。這樣的操作非常有用,因為根據以前的一部分棧幀中的局部變量的值,可能發現一些關于引起程序錯誤的代碼的線索。遍歷調用棧不會修改執行路徑,但是它確實允許查看幀的祖先幀,因此可以檢查通向當前幀的函數調用的局部變量的值。GDB的backtrace命令會顯示整個棧,即當前存在的所有幀的集合。

在GDB中,可以通過help命令訪問文檔。例如,”(gdb) help breakpoints”,將顯示關于斷點的文檔。不帶參數的GDB命令help提供了一個可用來作為help的參數的命令類別的菜單。

1.7 初涉調試會話:

注意,GCC中可以用-g選項讓編譯器將符號表(即對應于程序的變量和代碼行的內存地址列表)保存在生成的可執行文件中。這是一個絕對必要的步驟,這樣才能在調試會話過程中引用源代碼中的變量名和行號。

與接受行號(或函數名)的break命令不同,condition接受斷點號??偸强梢杂妹頸nfo break來查詢要查找的斷點的編號。用break if可以將break和condition命令組合成一個步驟,如下所示”(gdb) break 30 if num_y==1”,然后用run命令再次運行程序。如果要重用老的命令行參數,就不必再次指定命令行參數,可以簡單地輸入run。

我們在重新編譯程序之前仍然不必退出GDB。這樣做提供了很大的方便,第一,不需要重新指出命令行參數,只要鍵入run重新運行程序即可。其次,GDB保留了你設置的斷點,因此不需要再次鍵入它。同樣,在調試會話期間不要退出再重啟文本編輯器,這件事也會分心而且浪費時間。只要將文本編輯器放在一個窗口中,GDB放在另一個窗口中,用第三個窗口調試程序即可。

當運行程序試圖訪問不允許訪問的內存時發生了段錯誤。原因通常是由于數組索引超出了邊界,或者采用了錯誤的指針值。段錯誤也可能由每月顯式地包含指針或數組變量的內存引用產生。

1.8 啟動文件的使用:

在重新編譯代碼時,最好不要退出GDB。這樣,你的斷點和建立的其它各種動作都會保留。要是退出GDB,就不得不再次重復鍵入所有這些內容為了不丟失它們,可以將斷點和設置的其它命令放在一個GDB啟動文件中,然后每次啟動GDB時會自動加載它們。

GDB的啟動文件默認名為.gdbinit??梢詫⒁粋€文件放在主目錄中用于一般用途,另一個文件放在包含該項目特有用途的特定項目的目錄中。GDB在加載可執行文件之前會讀取主目錄中的啟動文件。在調用GDB時可以指定啟動文件,例如”$ gdb -command=z x”,表示要在可執行文件x上運行GDB,首先要從文件z中讀取命令。

2. 停下來環顧程序

2.1 暫停機制:有3種方式可以通知GDB暫停程序的執行:

(1).斷點:通知GDB在程序中的特定位置暫停執行。

(2).監視點:通知GDB當特定內存位置(或者涉及一個或多個位置的表達式)的值發生變化時暫停執行。

(3).捕獲點:通知GDB當特定事件發生時暫停執行。

2.2 斷點概述:在程序中的特定”位置”設置斷點,當到達那一點時,調試器會暫停程序的執行(在GDB這樣的基于文本的調試器的情況下,會出現命令行提示符)。GDB中關于”位置”的含義是非常靈活的,它可以指各種源代碼行、代碼地址、源代碼文件中的行號或者函數的入口等。

GDB命令行提示符上面顯式的語句信息是將要執行的代碼行,而不是GDB最后執行的代碼行,如下圖所示,接下來將要執行的是Messy_Test.cpp的第6行。GDB的工作針對的是機器語言指令,而不是源代碼行,一行代碼可能對應于數行機器語言。GDB之所以可以使用源代碼,是因為可執行文件中包含了額外的信息。

2.3 跟蹤斷點:程序員創建的每個斷點(包括斷點、監視點和捕獲點)都被標識為從1開始的唯一整數標識符。這個標識符用來執行該斷點上的各種操作。調試器還包括一種列出所有斷點及其屬性的方式。當創建斷點時,GDB會告知你分配給該斷點的編號。如果忘記了分配給哪個斷點的編號是什么,可以使用”(gdb) info breakpoints”命令來提示。通過使用delete命令以及斷點標識符,可以刪除斷點、監視點及捕獲點。

2.4 設置斷點:GDB中有許多指定斷點的方式,下面是一些最常見的方法:

(1).break funciton:在函數function的入口(第一行可執行代碼)處設置斷點。

(2).break line_number:在當前活動源代碼文件的line_number處設置斷點

(3).break filename:line_number:在源代碼文件filename的line_number處設置斷點。如果filename不在當前工作目錄中,則可以給出相對路徑名或者完全路徑名來幫助GDB查找該文件。

(4).break filename:function:在文件filename中的函數function的入口處設置斷點。重載函數或者使用同名靜態函數的程序可能需要使用這種形式。

當設置一個斷點時,該斷點的有效性會持續到刪除、禁用或退出GDB時。然而,臨時斷點是首次到達后就會被自動刪除的斷點。臨時斷點使用tbreak命令設置,它與break采用相同類型的參數GDB實際設置斷點的位置可能與請求將斷點放置的位置不同,當打開優化來編譯程序時,這個問題可能變得更糟糕。GDB最終使用的是機器指令。在調試完成前不應當優化代碼。

當GDB使用多個斷點中斷一行源代碼時,它只會中斷一次。換言之,當它到達該行代碼時,如果恢復執行,會忽略恰好在同一行上的其它斷點。事實上,GDB知道是哪個斷點”觸發”了程序停止執行。在具有多個斷點的代碼行上,觸發中斷的斷點將是標識符編號最小的斷點。

2.5 展開GDB示例:

啟動調試會話時在main()中設置斷點是非常普遍的。這一操作在該函數的第一行上設置斷點:”(gdb) break main”。

在任何給定時間,GDB都有一個焦點,可以將它看作當前”活動”文件。這意味著除非對命令做了限定,否則都是在具有GDB的焦點的文件上執行命令。默認情況下,具有GDB的初始焦點的文件是包含main()函數的文件,但是當發生如下任一動作時,焦點會轉移到不同的文件上:

(1).向不同的源文件應用list命令。

(2).進入位于不同的源代碼文件中的代碼。

(3).當在不同的源代碼文件中執行代碼時GDB遇到斷點。

使用quit命令離開GDB。

2.6 斷點的持久性:如果在修改和重新編譯代碼時沒有退出GDB,那么在下次執行GDB的run命令時,GDB會感知到代碼已修改,并自動重新加載新版本。然而要注意,斷點是會”移動”的。

2.7 刪除和禁用斷點:這里提到的一切方法都同樣適用于監視點。

GDB中有兩個用來刪除斷點的命令:delete和clear。delete命令用來基于標識符刪除斷點。clear命令使用與創建斷點相同的語法刪除斷點。

(1).delete breakpoint_list:刪除斷點使用數值標識符。斷點可以是一個數字,比如delete 2刪除第二個斷點;也可以是數字列表,比如delete 2 4刪除第二個和第四個斷點。

(2).delete:刪除所有斷點。

(3).clear:清除GDB將執行的下一個指令處的斷點。這種方法適用于要刪除GDB已經到達的斷點的情況。

(4).clear function、clear filename:funciton、clear line_number和clear filename:line_number:這些命令根據位置清除斷點,工作方式與對應的break命令相似。

每個斷點都可以被啟用或禁用。只有當GDB遇到啟用的斷點時,才會暫停程序的執行;它會忽略禁用的斷點。默認情況下,斷點的生命期從啟用時開始。在調試會話期間,會遇到大量斷點。對于經常重復的循環結構或函數,這種情況使得調試極不方便。如果要保留斷點以便以后使用,暫時又不希望GDB停止執行,可以禁用它們,在以后需要時再啟用。

使用disable breakpoint-list命令禁用斷點,使用enable breakpoint-list命令啟用斷點,其中breakpoint-list是使用空格分隔的列表,其中有一個或多個斷點標識符。不帶任何參數地執行disable命令將禁用所有現有斷點。類似地,不帶參數地執行enable命令會啟用所有現有斷點。還有一個enable once命令”enable once breakpoint-list”,在斷點下次引起GDB暫停執行后被禁用。這個命令與tbreak命令非常類似,但是當遇到斷點時,它是禁用斷點,而不是刪除斷點。

2.8 進一步介紹瀏覽斷點屬性:每個斷點都有各種屬性----行號、加在斷點上的條件(如果有的話)、當前啟用/禁用狀態等。

創建的每個斷點都被賦予了唯一的整數標識符。設置的第一個斷點被賦予”1”,其后的每個斷點都被賦予所賦的上一個標識符加1.每個斷點也有一些控制調整其行為的屬性。使用唯一標識符,可以分別調整各個斷點的屬性??梢允褂谩?gdb) info breakpoints”命令(簡寫為”i b”)來獲得設置的所有斷點的清單,以及它們的屬性。info breakpoints的輸出看上去或多或少類似于如下所示:

(1).標識符(Num):斷點的唯一標識符。

(2).類型(Type):這個字段指出該斷點是斷點、監視點還是捕獲點。

(3).部署(Disp):每個斷點都有一個部署,指示斷點下次引起GDB暫停程序的執行后該斷點上會發生什么事情。可能的部署有3種:

a.保持(keep):下次到達斷點后不改變斷點。這是新建斷點的默認部署。

b.刪除(del):下次到達斷點后刪除該斷點。使用tbreak命令創建的任何斷點都是這樣的斷點。

c.禁用(dis):下次到達斷點時會禁用該斷點。這是使用enable once命令設置的斷點。

(4).啟用狀態(Enb):這個字段說明斷點當前是啟用還是禁用的。

(5).地址(Address):這是內存中設置斷點的位置。它主要用于匯編語言程序員,或者試圖調試沒有用擴充的符號表編譯的可執行文件的人。

(6).位置(What):各個斷點位于源代碼中的特定行上。What字段顯示了斷點所在位置的行號和文件號。

2.9 恢復執行:方法有3類:

(1).使用step和next”單步”調試程序,僅執行代碼的下一行然后再次暫停。一旦GDB在斷點處停止,可以使用next(簡寫為n)和step(簡寫為s)命令來單步調試代碼。當觸發了斷點,并且GDB暫停后,可以使用next和step來執行緊接著的下一行代碼。當執行了這一行后,GDB會再次暫停,并給出一個命令行提示符。這兩個命令的區別是它們如何處理函數調用:next執行函數,不會在其中暫停,然后在調用之后的第一條語句處暫停。step在函數中的第一個語句處暫停。next將函數調用看作一行代碼,并在一個操作中執行整個函數,這稱為單步越過(stepping over)函數。next和step命令都采用一個可選的數值參數,表示要使用next或step執行的額外行數。換言之,next 3與在一行中鍵入next三次(或者鍵入next一次,然后按下ENTER鍵兩次)的作用相同。如果是在沒有函數調用的那部分代碼中,那么使用next還是step并沒有關系,在這種情況下,兩個命令是完全相同的

(2).由使用continue組成,使GDB無條件地恢復程序的執行,直到它遇到另一個斷點或者程序結束。簡寫為c,與僅執行一行代碼的step和next相反,這個命令使GDB恢復程序的執行,直到觸發斷點或者程序結束。continue命令可以接受一個可選的整數參數n,這個數字要求GDB忽略下面n個斷點。

(3).涉及條件,用finish或until命令恢復。在這種情況下,GDB會恢復執行,程序繼續運行直到遇到某個預先確定的條件(比如,到達函數的末尾),到達另一個斷點,或者程序完成。

使用finish恢復程序執行:想返回到單步進入被調用函數之前GDB所在的調用函數,這時應該使用finish命令finish命令(簡寫為fin)指示GDB恢復執行,直到恰好在當前棧幀完成之后為止。也就是說,這意味著如果你在一個不是main的函數中,finish命令會導致GDB恢復執行,直到恰好在函數返回之后為止。finish的另一個常見用途是當不小心單步進入原本希望單步越過的函數時(換言之,當需要使用next時使用了step),在這種情況下,使用finish可以將你正好放回到使用next會位于的位置。

如果在一個遞歸函數中,finish只會將你帶到遞歸的上一層。這是因為每次調用都被看作在它自己權限內的函數調用,因為每個函數都有各自的棧幀。如果要在遞歸層次較高時完全退出遞歸函數,那么更適合使用臨時斷點及continue,或者用until命令。

使用until恢復程序執行:finish命令在不進一步在函數中暫停(除了中間斷點)的情況下完成當前函數的執行。類似地,until命令(簡寫為u)通常用來在不進一步在循環中暫停(除了循環中的中間斷點)的情況下完成正在執行的循環,使用until會執行循環的其余部分,讓GDB在循環后面的第一行代碼處暫停。如果在循環的末尾,執行until命令導致回跳到循環頂部,這時只要再次執行until,就可以離開當前的循環。until命令也可以接受源代碼中的位置作為參數,事實上,該命令接受的參數與break命令相同。

2.10 條件斷點:這類似于監視點的工作方式,但是有一個重要區別。如果懷疑某個變量得到了一個偽值,那么條件斷點相當適用于監視點。每當該變量的值發生變化時,監視點都會中斷。條件斷點只會在懷疑有問題的代碼處當變量呈現該懷疑值時才中斷。設置條件斷點的語法為”break break-args if (condition)”。其中break-args是可以傳遞給break以指定斷點位置的任何參數,condition是定義的布爾表達式。括著condition的圓括號是可選的。如”(gdb) break main if argc > 1”:說明了如果用戶向程序中鍵入一些命令行參數,則在main()處中斷。條件中斷極其有用,尤其適用于索引變量的特定值出了問題的循環結構。條件中斷也極其靈活,不僅可以測試相等或不相等的變量。在有效的C條件語句中幾乎可以使用任何表達式。無論使用什么表達式,都需要具有布爾值,即真(非0)或假(0)

(1).相等、邏輯和不相等運算符(<、<=、==、!=、>、>=、&&、||等),如”(gdb) break 180 if string==nullptr && i < 0”

(2).按位和移位運算符(&、|、^、>>、<<等),如”(gdb) break test.c:34 if (x & y) == 1”

(3).算術運算符(+、-、*、/、%),如”(gdb) break myfunc if i % (j + 3) != 0”

(4).你自己的函數,只要它們被鏈接到程序中,如”(gdb) break test.c:myfunc if ! check_variable_sanity(i)”

(5).庫函數,只要該庫被鏈接到代碼中,例如:”(gdb) break 44 if strlen(mystring) == 0”

由于優先級的次序規則在起作用,因此可能需要使用圓括號將一些結構括起來。此外,如果在GDB表達式中使用庫函數,而該庫不是用調試符號編譯的(幾乎肯定是這種情況),那么唯一能在斷點條件中使用的返回值類型為int。換言之,如果沒有調試信息,GDB會假設函數的返回值是int類型。當這種假設不正確時,函數的返回值會被曲解。

可以對正常斷點設置條件以將它們轉變為條件斷點。例如,如果設置了斷點3作為無條件斷點,但是現在希望添加條件i==3,只要鍵入”(gdb) cond 3 i == 3”,如果以后要刪除條件,但是保持該斷點,只要鍵入”(gdb) cond 3”。

2.11 斷點命令列表:使用”斷點命令列表”可以讓GDB在每次到達某個斷點時自動執行一組命令,從而自動完成反復查看相同的變量這一過程。使用commands命令設置命令列表。逐條輸入命令,然后鍵入end表示輸入命令完畢,從那以后,每當GDB在這個斷點處中斷時,它都會執行你輸入的任何命令。

可以使用GDB的define命令創建宏。可以將宏保存在.gdbinit文件中,以便將它用于其它程序。鍵入”(gdb) show user”可以得到所有宏的列表。

2.12 監視點:是一種特殊類型的斷點,它類似于正常斷點,是要求GDB暫停程序執行的指令。區別在于監視點沒有”住在”某一行源代碼中,取而代之的是,監視點是指示GDB每當某個表達式改變了值就暫停執行的命令,如”(gdb) watch (i | j > 12) && i > 24 && strlen(name) > 6”??梢詫⒈O視點看作被”附加”在表達式上,當表達式的值改變時,GDB會暫停程序的執行。

雖然管理監視點和斷點的方式相同,但是兩者之間有一個重要區別。斷點與源代碼中的一個位置關聯。只要代碼沒有改變,就不存在某行代碼”超出作用域”的風險。因為C語言有嚴格的作用域規則,所以只能監視存在且在作用域內的變量。一旦變量不再存在于調用棧的任何幀中(當包含局部變量的函數返回時),GDB會自動刪除監視點。GDB只能監視單個線程中的變量

當變量var存在且在作用域中時,可以通過使用如下命令來設置監視點:”(gdb) watch var”,該命令會導致每當var改變值時GDB都中斷。GDB實際上是在var的內存位置改變值時中斷。監視點不僅僅限于監視變量,事實上,可以監視涉及變量的表達式,每當表達式修改值時,GDB都會中斷。

GDB中的表達式可以包含:

(1).GDB方便變量(convenience variables)。

(2).程序中的任何在作用域內的變量。

(3).任何種類的字符串、數值或字符常量。

(4).預處理器宏(如果程序被編譯為包括預處理器調試信息)。

(5).條件、函數調用、類型強制轉換和所用語言定義的運算符。

3. 檢查和設置變量

3.2 變量的高級檢查和設置:

GDB的display命令(簡寫為disp)在執行中每次有暫停(由于有斷點,使用next或step命令等)時就輸出指定條目的值,只有當變量在作用域中時才生效。

在GDB中可以輸出整個數組的值,如”(gdb) p x”或”(gdb) *pointer@number_of_elements”。

在GDB中,可以通過調用info locals命令得到當前棧幀中所有局部變量的值列表。

在有些情況下,可能希望檢查給定地址的內存,而不是通過變量的名稱。GDB為這種目的提供了x命令。

print和display命令允許指定可選的格式,如”(gdb) p/x y”,會以十六進制格式顯示變量,而不是十進制格式。其它常用的格式為c表示字符(character),s表示字符串(string),f表示浮點(floating-point)。

可以臨時禁用某個顯示項,例如”(gdb) dis disp 1”,臨時禁用顯示列表中的條目1.如果不知道條目號,可以通過info disp命令檢查。要重新啟用條目,使用enable,例如”(gdb) enable disp 1”。要完全刪除顯示的條目,使用undisplay,例如”(gdb) undisp 1”。

3.3 設置變量:”(gdb) set x = 12”,會將x的當前值改成12??梢酝ㄟ^GDB的set args命令設置程序的命令行參數,如”(gdb) set args 1 52 19 11”,并不會立即將argv[1]改成1,argv[2]改成52,等等,直到下次執行run命令時才會發生這些變化。GDB有用來檢查當前函數參數的info args命令。

3.4 GDB自己的變量:

(1).使用值歷史:GDB的print命令的輸出值被標為$1、$2等,這些值統稱為值歷史。在將來執行print命令時使用這樣的值歷史會比較方便,如”(gdb) p *$1”。

(2).方便變量(convenience variable):會根據C規則改變值。

4. 程序崩潰處理

4.2 核心文件:如果在程序運行期間創建了核心文件(core file,俗稱轉儲核心),則可以打開調試器(比如GDB)上的該文件,然后開始常規GDB操作。

核心文件包含程序崩潰時對程序狀態的詳細描述:棧的內容(或者,如果程序是多線程的,則是各個線程的棧),CPU寄存器的內容(同樣,如果程序是多線程的,則是每個線程上的一組寄存器值),程序的靜態分配變量的值(全局與static變量),等等。

大多數現代shell都會在一開始就防止編寫核心文件。在bash中,可以使用ulimit命令控制核心文件的創建?!? ulimit -c n”,其中n是核心文件的最大大小,以千字節為單位。超過nKB的任何核心文件都不會被編寫。如果沒有指定n,shell就會顯示核心文件上的當前限制。如果允許任意大小的核心文件,可以使用:”$ ulimit -c unlimited”。

如果程序的源代碼不可用,或者可執行文件不是用增強的符號表編譯的,甚或當我們沒有計劃調試可執行文件,核心文件可能都不會有太大的用處。

core file的使用示例可參考:https://blog.csdn.net/fengbingchun/article/details/97113451

4.3 擴展示例:

在調試會話期間,修改代碼時永遠不要退出GDB。這樣就不必費時間來啟動,可以保留我們的斷點,等等。類似地,我們要保持文本編輯器打開。在調試時的兩次編譯之間留在同一個編輯器會話中,我們可以充分利用編輯器的”撤銷”功能。例如,調試過程中的一個常見策略是臨時刪除部分代碼,以便集中精力于你認為存在程序錯誤的余下部分。完成檢查后,只要使用編輯器的撤銷功能恢復被刪除的代碼行即可。因此,在屏幕上我們通常有一個GDB窗口,以及一個編輯器窗口。我們還打開了第三個窗口用于執行編譯器命令,甚至最好是通過編輯器執行命令。

記住,當GDB注意到重新編譯了程序后,它會自動加載新的可執行文件,因此同樣不需要退出和重啟GDB

5. 多活動上下文中的調試

5.1 調試客戶/服務器網絡程序:socket

5.2 調試多線程代碼:

查看指定線程的棧,如線程3,可執行”(gdb) thread 3”,再執行”(gdb) bt”。多線程程序的運行有一定的隨機性。

下面是與線程相關的GDB命令用法匯總:

(1).info threads:給出關于當前所有線程的信息,帶有”*”號表示當前線程;

(2).thread 3:改成線程3;

(3).break 88 thread 3:當線程3到達源代碼行88時停止執行;

(4).break 88 thread 3 if x == y:當線程3到達源代碼行88,并且變量x和y相等時停止執行。

5.3 調試并行應用程序:共享內存和消息傳遞、MPI

5.4 擴展示例:OpenMP

6. 特殊主題

6.1 根本無法編譯或加載:

6.2 調試GUI程序:

7. 其它工具

8. 對其它語言使用GDB

GitHub:https://github.com/fengbingchun/Messy_Test

總結

以上是生活随笔為你收集整理的软件调试的艺术笔记:GDB的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。