首頁 > 軟體

五個 Linux 下使用者空間的偵錯工具

2020-06-16 18:04:51

根據定義,偵錯工具是那些那些使我們能夠監測、控制和糾正其他程式的程式。我們為什麼應該用偵錯工具呢? 在有些情況下,執行一些程式的時候我們會被卡住,我們需要明白究竟發生了什麼。 例如,我們正在執行應用程式,它產生了一些錯誤訊息。要修復這些錯誤,我們應該先找出為什麼產生這些錯誤的訊息和這些錯誤訊息從哪裡產生的。 一個應用程式可能突然掛起,我們必須了解其他什麼進程同時在執行。我們可能還必須弄清楚某個進程掛起的時候在做什麼。為了剖析這些細節, 我們需要偵錯工具的幫助。

有幾個Linux下的使用者空間偵錯工具和技術,它們用來分析使用者空間的問題相當有用。它們是:

  • 'print' 語句
  • 查詢 (/proc, /sys 等)
  • 跟蹤 (strace/ltrace)
  • Valgrind (memwatch)
  • GDB

讓我們一個個地了解。

1.'print' 語句

這是一個基本的原始的偵錯問題的方法。 我們可以在程式中插入print語句來了解控制流和變數值。 雖然這是一個簡單的技術, 但它有一些缺點。 程式需要進行編輯以新增'print'語句,然後必須重新編譯,重新執行來獲得輸出。 如果要偵錯的程式相當大,這是一個耗時的方法。

2. 查詢

在某些情況下,我們需要弄清楚在一個執行在核心中的進程的狀態和記憶體對映。為了獲得這些資訊,我們不需要在核心中插入任何程式碼。 相反,可以用 /proc 檔案系統。

/proc 是一個偽檔案系統,系統一啟動執行就收集著執行時系統的資訊 (cpu資訊, 記憶體容量等)。

'ls /proc'的輸出

正如你看到的, 系統中執行的每一個進程在/proc檔案系統中有一個以進程id命名的項。每個進程的細節資訊可以在進程id對應的目錄下的檔案中獲得。

'ls /proc/pid'的輸出

解釋/proc檔案系統內的所有條目超出了本文的範圍。一些有用的列舉如下:

  • /proc/cmdline -> 核心命令列
  • /proc/cpuinfo -> 關於處理器的品牌,型號資訊等
  • /proc/filesystems -> 檔案系統的核心支援的資訊
  • /proc/<pid>/cmdline -> 命令列引數傳遞到當前進程
  • /proc/<pid>/mem -> 當前進程持有的記憶體
  • /proc/<pid>/status -> 當前進程的狀態

3. 跟蹤

strace的和ltrace是兩個在Linux中用來追蹤程式的執行細節的跟蹤工具。

strace:

strace攔截和記錄系統呼叫及其接收的信號。對於使用者,它顯示了系統呼叫、傳遞給它們的引數和返回值。strace的可以附著到已在執行的進程或一個新的進程。它作為一個針對開發者和系統管理員的診斷、偵錯工具是很有用的。它也可以用來當做一個通過跟蹤不同的程式呼叫來了解系統的工具。這個工具的好處是不需要原始碼,程式也不需要重新編譯。

使用strace的基本語法是:

strace 命令

strace有各種各樣的引數。可以檢檢視strace的手冊頁來獲得更多的細節。

strace的輸出非常長,我們通常不會對顯示的每一行都感興趣。我們可以用'-e expr'選項來過濾不想要的資料。

用 '-p pid' 選項來綁到執行中的進程.

用'-o'選項,命令的輸出可以被重定向到檔案。

strace過濾成只有系統呼叫的輸出

ltrace:

ltrace跟蹤和記錄一個進程的動態(執行時)庫的呼叫及其收到的信號。它也可以跟蹤一個進程所作的系統呼叫。它的用法是類似與strace。

ltrace command

'-i' 選項在呼叫庫時列印指令指標。

'-S' 選項被用來現實系統呼叫和庫呼叫

所有可用的選項請參閱ltrace手冊。

ltrace捕捉'STRCMP'庫呼叫的輸出

4. Valgrind

Valgrind是一套偵錯和分析工具。它的一個被廣泛使用的預設工具——'Memcheck'——可以攔截malloc(),new(),free()和delete()呼叫。換句話說,它在檢測下面這些問題非常有用:

  • 記憶體洩露
  • 重釋放
  • 存取越界
  • 使用未初始化的記憶體
  • 使用已經被釋放的記憶體等。

它直接通過可執行檔案執行。

Valgrind也有一些缺點,因為它增加了記憶體占用,會減慢你的程式。它有時會造成誤報和漏報。它不能檢測出靜態分配的陣列的存取越界問題。

為了使用它,首先請下載並安裝在你的系統上。可以使用作業系統上的包管理器來安裝。

使用命令列安裝需要解壓縮和解包下載的檔案。

  1. tar -xjvf valgring-x.y.z.tar.bz2 (where x.y.z is the version number you are trying to install)

進入新建立的目錄(的valgrind-XYZ)內執行以下命令:

  1. ./configure
  2. make
  3. make install

讓我們通過一個小程式(test.c)來理解valgrind怎麼工作的:

  1. #include<stdio.h>
  2.  
  3. void f(void)
  4.  
  5. {
  6. int x = malloc(10*sizeof(int));
  7.  
  8. x[10]=0;
  9. }
  10.  
  11. int main()
  12. {
  13. f();
  14. return0;
  15. }

編譯程式:

  1. gcc -o test -g test.c

現在我們有一個可執行檔案叫做'test'。我們現在可以用valgrind來檢測記憶體錯誤:

  1. valgrind tool=memcheck leak-check=yes test

這是valgrind呈現錯誤的輸出:

valgrind顯示堆溢位和記憶體漏失的輸出

正如我們在上面看到的訊息,我們正在試圖存取函數f未分配的記憶體以及分配尚未釋放的記憶體。

5. GDB

GDB是來自自由軟體基金會的偵錯程式。它對定位和修復程式碼中的問題很有幫助。當被偵錯的程式執行時,它給使用者控制權去執行各種動作, 比如:

  • 啟動程式
  • 停在指定位置
  • 停在指定的條件
  • 檢查所需資訊
  • 改變程式中的資料 等。

你也可以將一個崩潰的程式coredump附著到GDB並分析故障的原因。

GDB提供很多選項來偵錯程式。 然而,我們將介紹一些重要的選擇,來感受如何開始使用GDB。

如果你還沒有安裝GDB,可以在這裡下載:GDB官方網站

編譯程式:

為了用GDB偵錯程式,必須使用gcc的'-g'選項進行編譯。這將以作業系統的本地格式產生偵錯資訊,GDB利用這些資訊來工作。

下面是一個簡單的程式(example1.c)執行被零除用來顯示GDB的用法:

  1. #include
  2. int divide()
  3. {
  4. int x=5, y=0;
  5. return x / y;
  6. }
  7.  
  8. int main()
  9. {
  10. divide();
  11. }

展示GDB用法的例子

呼叫 GDB:

通過在命令列中執行'gdb'來啟動gdb:

呼叫 gdb

呼叫後, 它將等待終端命令並執行,直到退出。

如果一個進程已經在執行,你需要將GDB連線到它上面,可以通過指定進程ID來實現。假設程式已經崩潰,要分析問題的原因,則用GDB分析core檔案。

啟動程式:

一旦你在GDB裡面,使用'run'命令來啟動程式進行偵錯。

給程式傳引數:

使用'set args'給你的程式傳引數,當程式下次執行時將獲得該引數。'show args'將顯示傳遞給程式的引數。

檢查堆疊:

每當程式停止,任何人想明白的第一件事就是它為什麼停止,以及怎麼停在那裡的。該資訊被稱為反向跟蹤。由程式產生每個函數呼叫和區域性變數,傳遞的引數,呼叫位置等資訊一起儲存在堆疊內的資料塊種,被稱為一幀。我們可以使用GDB來檢查所有這些資料。 GDB從最底層的幀開始給這些幀編號。

  • bt: 列印整個堆疊的回溯
  • bt 列印n個幀的回溯
  • frame : 切換到指定的幀,並列印該幀
  • up : 上移'n'個幀
  • down : 下移'n'個幀 ( n預設是1)

檢查資料:

程式的資料可以在裡面GDB使用'print'命令進行檢查。例如,如果'x'是偵錯程式內的變數,'print x'會列印x的值。

檢查原始碼:

原始碼可以在GDB中列印。預設情況下,'list'命令會列印10行程式碼。

  • list : 列出'linenum'行周圍的原始碼
  • list : 從'function'開始列出原始碼
  • disas : 顯示該函數機器程式碼

停止和恢復程式:

使用GDB,我們可以在必要的地方設定斷點,觀察點等來停止程式。

  • break : 在'location'設定一個斷點。當在程式執行到這裡時斷點將被擊中,控制權被交給使用者。
  • watch : 當'expr'被程式寫入而且它的值發生變化時GDB將停止
  • catch : 當'event'發生時GDB停止
  • disable : 禁用指定斷點
  • enable : 啟用指定斷點
  • delete : 刪除 斷點/觀察點/捕獲點。 如果沒有傳遞引數預設操作是在所有的斷點
  • step: 一步一步執行程式
  • continue: 繼續執行程式,直到執行完畢

退出 GDB:

用'quit'命令還從GDB中退出。

GDB還有更多的可用選項。裡面GDB使用help選項了解更多詳情。

在GDB中獲得幫助

總結

在這篇文章中,我們已經看到不同型別的Linux使用者空間的偵錯工具。總結以上所有內容,如下是什麼時候使用該什麼的快速指南:

  • 基本偵錯,獲得關鍵變數 - print 語句
  • 獲取有關檔案系統支援,可用記憶體,CPU,執行程式的核心狀態等資訊 - 查詢 /proc 檔案系統
  • 最初的問題診斷,系統呼叫或庫呼叫的相關問題,了解程式流程 – strace / ltrace
  • 應用程式記憶體空間的問題 – valgrind
  • 檢查應用程式執行時的行為,分析應用程式崩潰 – gdb

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-03/114920.htm


IT145.com E-mail:sddin#qq.com