linux調試技巧分享:strace、ltrace、objdump、valgrind

簡介

很多時候我們希望可以看到一個進程調用了哪些API以及其調用順序,例如我們要參考某個程序的實現,但我們又無法獲得該程序的源代碼時,使用系統調用跟蹤命令不失爲一個好辦法。另外,在一些無法調試的環境上檢查問題時,我們也可以用該命令來查看程序是否按預期執行。strace、ltrace、dtruss都是同一類型的命令,strace是linux系統上的,ltrace是debian類系統上的,而dtruss是mac系統上的。

strace常用來跟蹤進程執行時的系統調用和所接收的信號。 在Linux世界,進程不能直接訪問硬件設備,當進程需要訪問硬件設備(比如讀取磁盤文件,接收網絡數據等等)時,必須由用戶態模式切換至內核態模式,通 過系統調用訪問硬件設備。strace可以跟蹤到一個進程產生的系統調用,包括參數,返回值,執行消耗的時間。

命令

strace —— Trace system calls and signals。 跟蹤進程的系統調用或信號產生的情況。
ltrace —— A library call tracer。 跟蹤進程調用庫函數的情況。

strace: (該方法無法發現用戶寫出的程序或共享庫中發生的錯誤)
strace -o output.txt -T -tt -e trace=all -p 28979
( 跟蹤28979進程的所有系統調用(-e trace=all),並統計系統調用的花費時間,
以及開始時間(以時分秒格式顯示),最後將記錄結果存在output.txt文件裏面)



1.使用strace啓動進程(假設程序名st1)

    $ strace st1 (//從後往前看strace的輸出結果是解決問題的捷徑)
    添加-i選項即可顯示程序在哪個地址進行了系統調用,該地址可用作設置gdb的斷點。
    $ strace -i st1(各行開頭[]中的數字就是執行系統調用的代碼的地址)
    $ gdb st1
    (gdb) start
    (gdb) b *0x359debf310
    (gdb) c
    (gdb) bt


2.用strace查看運行中的進程(如守護進程)的行爲
    ps ux | grep st1(查找st2的進程ID)
    strace -p 17673(假如st進程ID爲17673)

3.將strace信息輸出到文件
$ strace -o output.log ./st1

4.重定向標準輸出
strace的輸出爲標準錯誤輸出,可以將顯示內容輸出到標準輸出上,通過管道傳給grep、less等
$ strace ./st1 2>&1 | grep open 
$ strace ./st1 2>&1 | less
(2>&1 將標準錯誤重定向到標準輸出 2> 標準錯誤重定向 &1 標準輸出)

5.跟蹤進程和fork()之後的進程
$ strace -f ./st1

6.顯示系統調用的執行時刻
$ strace -t ./st1 (以秒爲單位)
$ strace -tt ./st1 (以毫秒爲單位)

7.顯示特定的系統調用
strace -e open ./st1
strace -e trace=open ./st1
strace -e trace=all ./st1 (默認或-e trace=all表示要顯示所有系統調用)

7.ltrace 庫調用跟蹤(大部分用法基本上與strace一致)
ltrace ./st1

8.objdump 
如果二進制文件帶有調試信息,objdump可以將源代碼、文件名、行數、彙編代碼對應顯示,但是優化過的代碼可能會對應不準,只能作爲參考
objdump -Sl --no-show-raw-insn ./st1

9.valgrind
$ valgrind --tool=memchek --leak-check=yes ./st1
檢測內存非法使用(memchek )爲默認啓用的選項,所以也可以下面這樣
valgrind --leak-check=yes ./st1

valgrind並不是萬能的,例如對棧上生成的內存區域的非法訪問就無法檢測到
test.c
#include <stdlib.h>
int main(void)
{
    char p[10];
    p[100] = 1;
    return EXIT_SUCCESS;
}

valgrind可用來檢測內存泄漏、訪問非法內存地址、讀取未初始化內存區域、
訪問已釋放內存區域、內存雙重釋放、非法棧空間操作。

檢測內存泄漏還可以使用top命令,長時間監視內存的使用量。
如果內存泄漏,進程的使用量(VIRT和RES)會時間增長
VIRT和RES的區別是:VIRT包含了被交換(swap)出的空間,而RES不包含。

注意:在VIRT或RES逐漸增加的情況下,有時候不是內存泄漏,可能是庫函數
爲了提高效率而多分配了內存或者內存不需要時也不釋放而是當緩存使用,保持
內存佔用。但是這種多餘多餘分配的內存大小最多隻有幾MB而已。

 

//文字摘抄自《Debug_Hack》一書,更多應用程序的調試技巧,不妨去網上下載個電子書看看。

如有錯誤,歡迎留言,哪怕是錯別字也好,感謝!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章