您可以用各種方法來監控執行著的使用者空間程式:
可以為其執行偵錯程式並單步除錯該程式,新增列印語句, 或者新增工具來分析程式。本文描述了幾種可以用來除錯在 linux 上執行的程式的方法。我們將回顧四種除錯問題的情況,這些問題包括段錯誤,記憶體溢位和洩漏,還有掛起
當您的程式中包含錯誤時,很可能在**中某處有乙個條件,您認為它為真(true),但實際上是假(false)。找出錯誤的過程也就是在找出錯誤後推翻以前一直確信為真的某個條件過程。
以下幾個示例是您可能確信成立的條件的一些型別:
您可以使用 linux 上的除錯工具,通過各種方式跟蹤使用者空間和核心問題。請使用下面的工具和技術來構建和除錯您的源**:
使用者空間工具:
核心工具:
memwatch
只要在**中新增乙個標頭檔案並在 gcc 語句中定義了 memwatch 之後,您就可以跟蹤程式中的記憶體洩漏和錯誤了。memwatch 支援 ansi c,它提供結果日誌紀錄,能檢測雙重釋放(double-free)、錯誤釋放(erroneous free)、沒有釋放的記憶體(unfreed memory)、溢位和下溢等等。
gcc -dmemwatch -dmw_stdio test1.c memwatchc -o test1
#include #include #include "memwatch.h"int main(void)
清單 1 中的**將分配兩個 512 位元組的記憶體塊,然後指向第乙個記憶體塊的指標被設定為指向第二個記憶體塊。結果,第二個記憶體塊的位址丟失,從而產生了記憶體洩漏。
現在我們編譯清單 1 的 memwatch.c。下面是乙個 makefile 示例:
當您執行 test1 程式後,它會生成乙個關於****存的報告。清單 2 展示了示例 memwatch.log 輸出檔案。
清單 2. test1 memwatch.log 檔案
...double-free: <4> test1.c(15), 0x80517b4 was freed from test1.c(14)
...unfreed: <2> test1.c(11), 512 bytes at 0x80519e4
memory usage statistics (global):
n)umber of allocations made: 2
l)argest memory usage : 1024
t)otal of all alloc() calls: 1024
u)nfreed bytes totals : 512
memwatch 為您顯示真正導致問題的行。如果您釋放乙個已經釋放過的指標,它會告訴您。對於沒有釋放的記憶體也一樣。日誌結尾部分顯示統計資訊,包括洩漏了多少記憶體,使用了多少記憶體,以及總共分配了多少記憶體。
在程式設計時進行動態記憶體分配是非常必要的。它可以在程式執行的過程中幫助分配所需的記憶體,
而不是在程序啟動的時候就進行分配。當以前分配的一片記憶體不再需要使用或無法訪問時,但是卻並沒有釋放它,
那麼對於該程序來說,會因此導致總可用記憶體的減少,這時就出現了記憶體洩漏。由於設計錯誤,
失去了對該段記憶體的控制,因而造成了記憶體的浪費
valgrind(以後介紹)
valgrind是一款基於模擬linux下的程式偵錯程式和剖析器的軟體套件,可以執行於x86, amd64和ppc32架構上。valgrind包含乙個核心,它提供乙個虛擬的cpu執行程式,還有一系列的工具,它們完成除錯,剖析和一些類似的任務。valgrind是高度模組化的,所以開發人員或者使用者可以給它新增新的工具而不會損壞己有的結構。
第 2 種情況:使用 strace
strace
命令是一種強大的工具,它能夠顯示所有由使用者空間程式發出的系統呼叫。strace 顯示這些呼叫的引數並返回符號形式的值。strace 從核心接收資訊,而且不需要以任何特殊的方式來構建核心。將跟蹤資訊傳送到應用程式及核心開發者都很有用。在清單 6 中,分割槽的一種格式有錯誤,清單顯示了 strace 的開頭部分,內容是關於調出建立檔案系統操作(mkfs
)的。strace 確定哪個呼叫導致問題出現。
清單 6. mkfs 上 strace 的開頭部分
execve("/sbin/mkfs.jfs", ["mkfs.jfs", "-f", "/dev/test1"], &...open("/dev/test1", o_rdwr|o_largefile) = 4
stat64("/dev/test1", ) = 0
ioctl(4, 0x40041271, 0xbfffe128) = -1 einval (invalid argument)
write(2, "mkfs.jfs: warning - cannot setb" ..., 98mkfs.jfs: warning -
cannot set blocksize on block device /dev/test1: invalid argument )
= 98
stat64("/dev/test1", ) = 0
open("/dev/test1", o_rdonly|o_largefile) = 5
ioctl(5, 0x80041272, 0xbfffe124) = -1 einval (invalid argument)
write(2, "mkfs.jfs: can\'t determine device"..., ..._exit(1)
= ?
清單 6 顯示ioctl
呼叫導致用來格式化分割槽的mkfs
程式失敗。ioctl blkgetsize64
失敗。(blkget-size64
在呼叫ioctl
的源**中定義。)blkgetsize64 ioctl
將被新增到 linux 中所有的裝置,而在這裡,邏輯卷管理器還不支援它。因此,如果blkgetsize64 ioctl
呼叫失敗,mkfs **將改為呼叫較早的ioctl
呼叫;這使得mkfs
適用於邏輯卷管理器。
使用gdb program name
命令啟動 gdb。gdb 將載入可執行程式符號並顯示輸入提示符,讓您可以開始使用偵錯程式。您可以通過三種方式用 gdb 檢視程序:
kgdb
kgdb 程式(使用 gdb 的遠端主機 linux 核心偵錯程式)提供了一種使用 gdb 除錯 linux 核心的機制。kgdb 程式是核心的擴充套件,它讓您能夠在遠端主機上執行 gdb 時連線到執行用 kgdb 擴充套件的核心機器。您可以接著深入到核心中、設定斷點、檢查資料並進行其它操作(類似於您在應用程式上使用 gdb 的方式)。這個補丁的主要特點之一就是執行 gdb 的主機在引導過程中連線到目標機器(執行要被除錯的核心)。這讓您能夠盡早開始除錯。請注意,補丁為 linux 核心新增了功能,所以 gdb 可以用來除錯 linux 核心。
使用 kgdb 需要兩台機器:一台是開發機器,另一台是測試機器。一條序列線(空數據機電纜)將通過機器的串列埠連線它們。您希望除錯的核心在測試機器上執行;gdb 在開發機器上執行。gdb 使用序列線與您要除錯的核心通訊。
請遵循下面的步驟來設定 kgdb 除錯環境:
將元件構建到核心,因為這是使用 kgdb 最簡單的方法。(請注意,有兩種方法可以構建多數核心元件,比如作為模組或直接構建到核心中。舉例來說,日誌紀錄檔案系統(journaled file system,jfs)可以作為模組構建,或直接構建到核心中。通過使用 gdb 補丁,我們就可以將 jfs 直接構建到核心中。)
應用核心補丁並重新構建核心。
建立乙個名為 .gdbinit 的檔案,並將其儲存在核心原始檔子目錄中(換句話說就是 /usr/src/linux)。檔案 .gdbinit 中有下面四行**:
Linux下GDB除錯簡介
gdb gnu debugger 是linux下的乙個除錯工具,具體的功能有 設定斷點,使得 在制定行暫停執行 單步除錯程式 檢視程式中的變數值的變化 動態改變程式的執行環境 分析崩潰程式產生的core檔案 假設我們有原始檔hello.c,要使用gdb進行除錯,在程式編譯時就必須使用 g或者 gdb...
jdb 除錯android 簡介
jdb 包含在jdk,使用jdb 之前需要先配置jdk的環境變數。jdb 常用於三方apk 無原始碼動態除錯,與其配合的工具為 baksmali apkanalyser,通過apkanalyser列印堆疊,理清楚正常情況下的 流程。使用baksmali,獲取 相關 的方法名,變數名,使用jdb 動態...
C 除錯幫助簡介
主要思想是 程式所包含的除錯 僅在開發過程中執行。當應用程式已經完成,並且準備提交時,就會將除錯 關閉。這種方法會用到兩項預處理功能 assert 和ndebug。定義在標頭檔案中 的所謂預處理巨集其實是乙個預處理變數,它的行為有點類似於內聯函式。使用乙個表示式作為它的條件 assert expr ...