搞電子都知道,電路不是焊接出來的,是調試出來的。程序員也必定認同,程序不是寫出來的,是調試出來的。那麼調試工具就顯得尤其重要,linux做爲筆者重要的開發平臺,在linux中討論調試工具主要是爲那些入門者提供一些幫助。調試工具能讓咱們可以監測、控制和糾正正在運行的程序。咱們在運行一些程序的時候,可能被卡住或出現錯誤,或者運行過程或結果,沒能如咱們預期,此時,最迫切須要明白究竟發生了什麼。爲了修復程序,剖析和了解程序運行的細節, 調試工具就成爲了咱們的必備工具,工於善其事,必先利其器。在Linux下的用戶空間調試工具主要有系統工具和專門調試工具:'print' 打印語句,這是新手最經常使用的,也是最不提倡使用的;查詢 (/proc, /sys 等)系統的虛擬文件查看,這個方法有侷限性;跟蹤 (strace/ltrace)工具使用這個比較廣泛,值得提倡;Valgrind (memwatch)內存排除工具,在內存排除方面比較獨到,是內存排錯的法寶;GDB大名鼎鼎的程序調試工具,這個是個全能的工具,沒有完不成的,只有你不知道的。html
這是一個基本的調試問題的方法。 咱們在程序中懷疑的地方插入print語句來了解程序的運行流程控制流和變量值的改變。 這是一個最簡單的技術, 它的缺點。 須要進行程序編輯,添加'print'語句,必須從新編譯,從新運行來得到輸出。若須要調試的程序比較大,這將是一個耗時費力的方法。linux
在某些狀況下,咱們須要弄清楚在一個運行在內核中的進程的狀態和內存映射。爲了得到這些信息,咱們不須要在內核中插入任何代碼。 相反,能夠用 /proc 文件系統。在/proc的僞文件系統,保留系統啓動運行就收集的運行時信息 (cpu信息, 內存容量等)。程序員
ls -l /proc'的輸出結果,經過對 系統中運行的每個進程在/proc文件系統中有一個以進程id命名的項。每一個進程的細節信息能夠在進程id對應的目錄下的文件中得到。也能夠'ls /proc/pid'的輸出小程序
解釋/proc文件系統內的全部條目超出了本文的範圍。一些有用的列舉以下:數組
strace的和ltrace是兩個在Linux中用來追蹤程序的執行細節的跟蹤工具。ide
strace攔截和記錄系統調用及其接收的信號。對於用戶,它顯示了系統調用、傳遞給它們的參數和返回值。strace的能夠附着到已在運行的進程或一個新的進程。它做爲一個針對開發者和系統管理員的診斷、調試工具是頗有用的。它也能夠用來當作一個經過跟蹤不一樣的程序調用來了解系統的工具。這個工具的好處是不須要源代碼,程序也不須要從新編譯。函數
使用strace的基本語法是:工具
strace 命令網站
strace有各類各樣的參數。能夠檢查看strace的手冊頁來得到更多的細節。ui
strace的輸出很是長,咱們一般不會對顯示的每一行都感興趣。咱們能夠用'-e expr'選項來過濾不想要的數據。
用 '-p pid' 選項來綁到運行中的進程.
用'-o'選項,命令的輸出能夠被重定向到文件。
strace過濾成只有系統調用的輸出
ltrace跟蹤和記錄一個進程的動態(運行時)庫的調用及其收到的信號。它也能夠跟蹤一個進程所做的系統調用。它的用法是相似與strace。
ltrace command
'-i' 選項在調用庫時打印指令指針。
'-S' 選項被用來現實系統調用和庫調用
全部可用的選項請參閱ltrace手冊。
ltrace捕捉'STRCMP'庫調用的輸出
Valgrind是一套調試和分析工具。它的一個被普遍使用的默認工具——'Memcheck'——能夠攔截malloc(),new(),free()和delete()調用。換句話說,它在檢測下面這些問題很是有用:
它直接經過可執行文件運行。
Valgrind也有一些缺點,由於它增長了內存佔用,會減慢你的程序。它有時會形成誤報和漏報。它不能檢測出靜態分配的數組的訪問越界問題。
爲了使用它,首先請下載並安裝在你的系統上。可使用操做系統上的包管理器來安裝。
使用命令行安裝須要解壓縮和解包下載的文件。
進入新建立的目錄(的valgrind-XYZ)內運行如下命令:
讓咱們經過一個小程序(test.c)來理解valgrind怎麼工做的:
編譯程序:
gcc -o test -g test.c
如今咱們有一個可執行文件叫作'test'。咱們如今能夠用valgrind來檢測內存錯誤:
valgrind –tool=memcheck –leak-check=yes test
這是valgrind呈現錯誤的輸出:
valgrind顯示堆溢出和內存泄漏的輸出
正如咱們在上面看到的消息,咱們正在試圖訪問函數f未分配的內存以及分配還沒有釋放的內存。
GDB是來自自由軟件基金會的調試器。它對定位和修復代碼中的問題頗有幫助。當被調試的程序運行時,它給用戶控制權去執行各類動做, 好比:
你也能夠將一個崩潰的程序coredump附着到GDB並分析故障的緣由。
GDB提供不少選項來調試程序。 然而,咱們將介紹一些重要的選擇,來感覺如何開始使用GDB。
若是你尚未安裝GDB,能夠在這裏下載:GDB官方網站。
爲了用GDB調試程序,必須使用gcc的'-g'選項進行編譯。這將以操做系統的本地格式產生調試信息,GDB利用這些信息來工做。
下面是一個簡單的程序(example1.c)執行被零除用來顯示GDB的用法:
展現GDB用法的例子
經過在命令行中執行'gdb'來啓動gdb:
調用 gdb
調用後, 它將等待終端命令並執行,直到退出。
若是一個進程已經在運行,你須要將GDB鏈接到它上面,能夠經過指定進程ID來實現。假設程序已經崩潰,要分析問題的緣由,則用GDB分析core文件。
一旦你在GDB裏面,使用'run'命令來啓動程序進行調試。
使用'set args'給你的程序傳參數,當程序下次運行時將得到該參數。'show args'將顯示傳遞給程序的參數。
每當程序中止,任何人想明白的第一件事就是它爲何中止,以及怎麼停在那裏的。該信息被稱爲反向跟蹤。由程序產生每一個函數調用和局部變量,傳遞的參數,調用位置等信息一塊兒存儲在堆棧內的數據塊種,被稱爲一幀。咱們可使用GDB來檢查全部這些數據。 GDB從最底層的幀開始給這些幀編號。
程序的數據能夠在裏面GDB使用'print'命令進行檢查。例如,若是'x'是調試程序內的變量,'print x'會打印x的值。
源碼能夠在GDB中打印。默認狀況下,'list'命令會打印10行代碼。
使用GDB,咱們能夠在必要的地方設置斷點,觀察點等來中止程序。
用'quit'命令還從GDB中退出。
GDB還有更多的可用選項。裏面GDB使用help選項瞭解更多詳情。
在GDB中得到幫助
在這篇文章中,咱們已經看到不一樣類型的Linux用戶空間的調試工具。總結以上全部內容,以下是何時使用該什麼的快速指南: