天天看點

點評五款用于 Linux 程式設計的記憶體調試器點評五款用于 Linux 程式設計的記憶體調試器

點評五款用于 Linux 程式設計的記憶體調試器點評五款用于 Linux 程式設計的記憶體調試器

作為一個程式員,我知道我肯定會犯錯誤——怎麼可能不犯錯!程式員也是人啊。有的錯誤能在編碼過程中及時發現,而有些卻得等到軟體測試了才能顯露出來。然而,還有一類錯誤并不能在這兩個階段被解決,這就導緻軟體不能正常運作,甚至是提前終止。

幸運的是,現在有一些程式設計工具能夠幫你在軟體程式中找到這些和記憶體相關的錯誤。在這些工具集中,我評估了五款支援 linux 的、流行的、自由開源的記憶體調試器: dmalloc 、 electric fence 、 memcheck 、 memwatch 以及 mtrace 。在日常編碼中,我已經用過這五個調試器了,是以這些評估是建立在我的實際體驗之上的。

<a></a>

開發者:gray watson

評估版本:5.5.2

支援的 linux 版本:所有種類

許可: cc 3.0

dmalloc 是 gray watson 開發的一款記憶體調試工具。它是作為庫來實作的,封裝了标準記憶體管理函數如<code>malloc()</code> , <code>calloc() </code>,<code> free()</code>等,使程式員得以檢測出有問題的代碼。

點評五款用于 Linux 程式設計的記憶體調試器點評五款用于 Linux 程式設計的記憶體調試器

dmalloc

dmalloc 最大的優點就是高度可配置性。比如說,你可以配置它以支援 c++ 程式和多線程應用。 dmalloc 還提供一個有用的功能:運作時可配置,這表示在 dmalloc 執行時,可以輕易地啟用或者禁用它提供的一些特性。

跟 mtrace 一樣, dmalloc 需要程式員改動他們的源代碼。比如說你可以(也是必須的)添加頭檔案<code>dmalloc.h</code>,工具就能彙報産生問題的調用的檔案或行号。這個功能非常有用,因為它節省了調試的時間。

除此之外,還需要在編譯你的程式時,把 dmalloc 庫(編譯 dmalloc 源碼包時産生的)連結進去。

dmalloc 真正的優勢在于它的可配置選項。而且高度可移植,曾經成功移植到多種作業系統如 aix 、 bsd/os 、 dg/ux 、 free/net/openbsd 、 gnu/hurd 、 hpux 、 irix 、 linux 、 ms-dog 、 next 、 osf 、 sco 、 solaris 、 sunos 、 ultrix 、 unixware 甚至 unicos(運作在 cray t3e 主機上)。雖然使用 dmalloc 需要學習許多知識,但是它所提供的特性值得為之付出。

開發者:bruce perens

評估版本:2.2.3

許可:gpl v2

點評五款用于 Linux 程式設計的記憶體調試器點評五款用于 Linux 程式設計的記憶體調試器

electric fence

我喜歡 electric fence 的首要一點是它不同于 memwatch 、 dmalloc 和 mtrace ,不需要對你的源碼做任何的改動,你隻需要在編譯的時候把它的庫連結進你的程式即可。

其次, electric fence 的實作保證了産生越界通路的第一個指令就會引起段錯誤。這比在後面再發現問題要好多了。

不管是否有檢測出錯誤, electric fence 都會在輸出産生版權資訊。這一點非常有用,由此可以确定你所運作的程式已經啟用了 electric fence 。

另一方面,我對 electric fence 真正念念不忘的是它檢測記憶體洩漏的能力。記憶體洩漏是 c/c++ 軟體最常見也是最不容易發現的問題之一。不過, electric fence 不能檢測出棧溢出,而且也不是線程安全的。

由于 electric fence 會在使用者配置設定記憶體區的前後配置設定禁止通路的虛拟記憶體頁,如果你過多的進行動态記憶體配置設定,将會導緻你的程式消耗大量的額外記憶體。

最後一點,盡管 electric fence 能檢測出大部分的緩沖區溢出,有一個例外是,如果所申請的緩沖區大小不是系統字長的倍數,這時候溢出(即使隻有幾個位元組)就不能被檢測出來。

盡管局限性較大, electric fence 的易用性仍然是加分項。隻要連結一次程式, electric fence 就可以在監測出記憶體相關問題的時候報警。不過,如同前面所說, electric fence 需要配合像 gdb 這樣的源碼調試器使用。

評估版本:3.10.1

支援的 linux 發行版:所有種類

許可:gpl

memcheck ,一款記憶體錯誤檢測器,是其中最受歡迎的工具。它能夠檢測出如記憶體洩漏、無效的記憶體通路、未定義變量的使用以及堆記憶體配置設定和釋放相關的問題等諸多問題。

同其它所有 valgrind 工具一樣, memcheck 也是指令行程式。它的操作非常簡單:通常我們會使用諸如 <code>prog arg1 arg2</code> 格式的指令來運作程式,而 memcheck 隻要求你多加幾個值即可,如 <code>valgrind --leak-check=full prog arg1 arg2</code> 。

點評五款用于 Linux 程式設計的記憶體調試器點評五款用于 Linux 程式設計的記憶體調試器

memcheck

(注意:因為 memcheck 是 valgrind 的預設工具,是以在指令行執行指令時無需提及 memcheck。但是,需要在編譯程式之初帶上 <code>-g</code> 參數選項,這一步會添加調試資訊,使得 memcheck 的錯誤資訊會包含正确的行号。)

我真正傾心于 memcheck 的是它提供了很多指令行選項(如上所述的<code>--leak-check</code>選項),如此不僅能控制工具運轉還可以控制它的輸出。

舉個例子,可以開啟<code>--track-origins</code>選項,以檢視程式源碼中未初始化的資料;可以開啟<code>--show-mismatched-frees</code>選項讓 memcheck 比對記憶體的配置設定和釋放技術。對于 c 語言所寫的代碼, memcheck 會確定隻能使用<code>free()</code>函數來釋放記憶體,<code>malloc()</code>函數來申請記憶體。而對 c++ 所寫的源碼, memcheck 會檢查是否使用了<code>delete</code>或<code>delete[]</code>操作符來釋放記憶體,以及<code>new</code>或者<code>new[]</code>來申請記憶體。

memcheck 最好的特點,尤其是對于初學者來說,是它會給使用者建議使用哪個指令行選項能讓輸出更加有意義。比如說,如果你不使用基本的<code>--leak-check</code>選項, memcheck 會在輸出時給出建議:“使用 --leak-check=full 重新運作以檢視更多洩漏記憶體細節”。如果程式有未初始化的變量, memcheck 會産生資訊:“使用 --track-origins=yes 以檢視未初始化變量的定位”。

無論是對于初學者還是那些需要進階特性的人來說, memcheck 都是一款便捷的記憶體調試工具。如果你僅需要基本調試和錯誤檢查, memcheck 會非常容易上手。而當你想要使用像抑制檔案或者監控指令這樣的特性,就需要花一些功夫學習了。

開發者:johan lindh

評估版本:2.71

許可:gnu gpl

memwatch 支援用 c 語言所編寫的程式。也可以在 c++ 程式中使用它,但是這種做法并不提倡(由 memwatch 源碼包随附的 q&amp;a 檔案中可知)。

這個版本添加了<code>ulong_long_max</code>以區分 32 位和 64 位程式。

跟 dmalloc 一樣, memwatch 也有優秀的文檔資料。參考 using 檔案,可以學習如何使用 memwatch ,可以了解 memwatch 是如何初始化、如何清理以及如何進行 i/o 操作,等等。還有一個 faq 檔案,旨在幫助使用者解決使用過程遇到的一般問題。最後還有一個<code>test.c</code>檔案提供工作案例參考。

點評五款用于 Linux 程式設計的記憶體調試器點評五款用于 Linux 程式設計的記憶體調試器

memwatch

不同于 mtrace , memwatch 産生的日志檔案(通常是<code>memwatch.log</code>)是人類可閱讀的格式。而且, memwatch 每次運作時總會把記憶體調試結果拼接到輸出該檔案的末尾。如此便可在需要之時輕松檢視之前的輸出資訊。

另一個我喜歡的優點是 memwatch 還提供了在源碼中擷取其輸出資訊的方式,你可以擷取資訊,然後任由你進行處理(參考 memwatch 源碼中的<code>mwsetoutfunc()</code>函數擷取更多有關的資訊)。

跟 mtrace 和 dmalloc 一樣, memwatch 也需要你往你的源檔案裡增加代碼:你需要把<code>memwatch.h</code>這個頭檔案包含進你的代碼。而且,編譯程式的時候,你需要連同<code>memwatch.c</code>一塊編譯;或者你可以把已經編譯好的目标子產品包含起來,然後在指令行定義<code>memwatch</code>和<code>mw_stdio</code>變量。不用說,想要在輸出中定位行号, -g 編譯器選項也少不了。

此外, memwatch 缺少一些特性。比如 memwatch 不能檢測出對一塊已經被釋放的記憶體進行寫入操作,或是在配置設定的記憶體塊之外的進行讀取操作。而且, memwatch 也不是線程安全的。還有一點,正如我在開始時指出,在 c++ 程式上運作 memwatch 的結果是不能預料的。

memcheck 可以檢測很多記憶體相關的問題,在處理 c 程式時是非常便捷的調試工具。因為源碼小巧,是以可以從中了解 memcheck 如何運轉,有需要的話可以調試它,甚至可以根據自身需求擴充更新它的功能。

開發者: roland mcgrath 和 ulrich drepper

評估版本: 2.21

點評五款用于 Linux 程式設計的記憶體調試器點評五款用于 Linux 程式設計的記憶體調試器

mtrace

mtrace 實際上是實作了一個名為<code>mtrace()</code>的函數,它可以跟蹤程式中所有 malloc/free 調用,并在使用者指定的檔案中記錄相關資訊。檔案以一種機器可讀的格式記錄資料,是以有一個 perl 腳本——同樣命名為 mtrace ——用來把檔案轉換并為人類可讀格式。

mtrace 最好的地方是它非常簡單易學。你隻需要了解在你的源碼中如何以及何處添加 <code>mtrace()</code> 及對應的<code>muntrace()</code> 函數,還有如何使用 mtrace 的 perl 腳本。後者非常簡單,隻需要運作指令<code>mtrace &lt;program-executable&gt; &lt;log-file-generated-upon-program-execution&gt;</code>(例子見開頭截圖最後一條指令)。

mtrace 另外一個優點是它的可伸縮性,這展現在不僅可以使用它來調試完整的程式,還可以使用它來檢測程式中獨立子產品的記憶體洩漏。隻需在每個子產品裡調用<code>mtrace()</code>和<code>muntrace()</code>即可。

使用 mtrace ,你需要掌握 linux 環境變量的基本知識,因為在程式執行之前,需要把使用者把環境變量<code>malloc_trace</code>的值設為指定的檔案(<code>mtrace()</code>函數将會記錄全部資訊到其中)路徑。

不言自明,我在此讨論的每款記憶體調試器都有其優點和局限。是以,哪一款适合你取決于你所需要的特性,雖然有時候容易安裝和使用也是一個決定因素。

要想捕獲軟體程式中的記憶體洩漏, mtrace 最适合不過了。它還可以節省時間。由于 linux 系統已經預裝了此工具,對于不能聯網或者不可以下載下傳第三方調試調試工具的情況, mtrace 也是極有助益的。

另一方面,相比 mtrace , dmalloc 不僅能檢測更多錯誤類型,還提供更多特性,比如運作時可配置、 gdb 內建。而且, dmalloc 不像這裡所說的其它工具,它是線程安全的。更不用說它的詳細資料了,這讓 dmalloc 成為初學者的理想選擇。

雖然 memwatch 的資料比 dmalloc 的更加豐富,而且還能檢測更多的錯誤種類,但是你隻能在 c 語言寫就的程式中使用它。一個讓 memwatch 脫穎而出的特性是它允許在你的程式源碼中處理它的輸出,這對于想要定制輸出格式來說是非常有用的。

如果改動程式源碼非你所願,那麼使用 electric fence 吧。不過,請記住, electric fence 隻能檢測兩種錯誤類型,而此二者均非記憶體洩漏。還有就是,需要基本了解 gdb 以最大化發揮這款記憶體調試工具的作用。

memcheck 可能是其中綜合性最好的了。相比這裡提及的其它工具,它能檢測更多的錯誤類型,提供更多的特性,而且不需要你的源碼做任何改動。但請注意,基本功能并不難上手,但是想要使用它的進階特性,就必須學習相關的專業知識了。

本文來自雲栖社群合作夥伴“linux中國”

原文釋出時間為:2013-04-02.

繼續閱讀