歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> Unix基礎知識 >> 在AIX V5.3中使用MALLOCDEBUG隔離並解決內存洩漏-用於完成煩瑣任務的有用工具

在AIX V5.3中使用MALLOCDEBUG隔離並解決內存洩漏-用於完成煩瑣任務的有用工具

日期:2017/3/3 15:24:44   编辑:Unix基礎知識

AIX® Version 5.3 中附帶的 malloc 子系統監視工具 MALLOCDEBUG,可以幫助您隔離內存洩漏。 內存洩漏是非常棘手的問題,並且處理起來需要很大的代價,所以使用好的工具以確定並了解出現洩漏的 原因是非常重要的。本文中提供的示例代碼將向您展示處理內存洩漏的一種方法。

引言

在編寫應用程序時進行動態內存分配是非常必要的。它可以在程序運行的過程中幫助分配所需的內存 ,而不是在進程啟動的時候就進行分配。然而,有效地管理這些內存同樣也是非常重要的。在大型的、復 雜的應用程序中,內存洩漏是很常見的問題。當以前分配的一片內存不再需要使用或無法訪問時,但是卻 並沒有釋放它,那麼對於該進程來說,會因此導致總的可用內存的減少,這時就出現了內存洩漏。盡管優 秀的編程實踐可以確保最少的洩漏,但是根據經驗,當使用大量的函數對相同的內存塊進行處理時,很可 能會出現內存洩漏。尤其是在碰到錯誤路徑的情況下更是如此。

本文介紹了一種內存洩漏處理方法,並討論了如何利用 AIX® 中附帶的 MALLOCDEBUG 工具。

為什麼內存洩漏難以解決

應用程序可以根據所碰到的具體情況,在其生命周期中的不同時刻釋放一片內存。編程人員需要對應 用程序進行合理的設計,以便它能夠知道何時可以釋放一塊內存,並馬上執行這個操作,而不是等待更長 的時間。根據具體的控制流程,可以在代碼中的不同地方進行內存的釋放。有一點至關重要,那就是必須 涉及到所有的控制流程,而不僅僅是最常執行的代碼流程路徑。

同時,在內存做好釋放准備之前對其進行釋放可能引起災難性的錯誤。因此,要了解內存塊在何處做 好了釋放的准備,必須全面地了解應用程序中的控制流程。

檢測內存洩漏

當出現下列症狀時,表示可能出現了洩漏:

malloc 返回的 errno 被設置為 ENOMEM。

發生核心轉儲,並且堆棧中的一個函數來自於 malloc 子系統。

在進行核心轉儲時,進程的大小比正常運行時要大。

進程大小(可以使用 ps 命令來查看)急劇增長。

如果出現了一些內存洩漏的症狀,那麼最好使用內存監視工具進行分析。有許多第三方的工具,如 Zerofault 和 IBM Rational® Purify®,但本文將討論 AIX 中附帶的 MALLOCDEBUG 工具。

使用 MALLOCDEBUG 報告內存洩漏

MALLOCDEBUG 是一種很易於使用的 malloc 子系統監視工具。通過使用兩個環境變量 MALLOCDEBUG 和 MALLOCTYPE,您可以輕松地對特定的應用程序啟用 malloc 子系統調試任務。您需要將這些變量導出到運 行該應用程序的 Shell 中。在 AIX Version 5.3 中,錯誤報告將寫入到 stderr。

MALLOCTYPE

MALLOCTYPE 變量用來確定應該使用何種 malloc 子系統,以及是否啟用調試任務。下面的表 1 顯示 了 MALLOCTYPE 各種可能的取值。請參見參考資料部分,其中提供了“Developing and Porting C and C++ Applications on AIX”的鏈接。IBM 紅皮書。

表 1. MALLOCTYPE 變量

MALLOCTYPE= 內存分配器 IBM 紅皮書“Developing and Porting C and C++ Applications on AIX” 中的詳細解釋 3.1 3.1 內存分配器 4.2.1 節,3.1 內存分配器 NULL 缺省內存分配器 4.2.2 節,缺省內存分配器 buckets 具有 malloc 桶擴展的缺省內存分配器 4.2.3 節,具有 malloc 桶擴展的缺省內存分配器 debug 調試內存分配器 4.2.4 節,調試內存分配器 user:archive_name 用戶定義的內存分配器 4.2.5 節,用戶定義的內存分配器

您應該清楚,MALLOCDEBUG 假定使用的是缺省分配器。

MALLOCDEBUG

MALLOCDEBUG 變量可以包含下面表 2 的列表中的多個值,這些值之間以逗號分隔。

表 2. MALLOCDEBUG 變量

MALLOCDEBUG= 簡要解釋 Align:n n 是內存對齊的數值。關於更多的信息,請參見參考資料部分。 postfree_checking postfree_checking 使得 MALLOCDEBUG 報告對已釋放的內存進行訪問的嘗試,然後中 止該程序。 validate_ptrs 如果向 free() 調用傳遞的指針並不是以前由 malloc 分配的,那麼將會引發一個錯誤 消息,而該程序將被中止。 override_signal_handling 當 MALLOCDEBUG 檢測到內存錯誤,它會強迫該程序使用 SIGSEGV 或 SIGABRT 進行核 心轉儲。設置 override_signal_handling 可以確保該程序終止並進行核心轉儲,即使應用程序已經對這 些信號進行了處理。 allow_overreading allow_overreading 將忽略讀取越界。 report_allocations report_allocations 將報告在應用程序退出時所有未釋放的內存分配。 record_allocations record_allocations 將報告所有的內存分配。 continue 繼續報告錯誤,但它並不異常終止 (ABEND) 該程序。這是 AIX Version 5.3 中提供的 一種非常有用的特性。 stack_depth:n stack_depth:n 將錯誤堆棧報告到第 n 層,而不是缺省的第 6 層。

在這些選項中,使用 report_allocations 最為合適,因為它可以為您提供已檢測到的應用程序中洩 漏的列表。

示例

在這一部分中,您將看到一個示例和一些示例代碼清單,用以說明如何使用 MALLOCDEBUG。下載部分 中提供了這個示例的源代碼。

清單 1. 將 MALLOCDEBUG 和 MALLOCTYPE 設置導出到 Shell/home/user> export MALLOCTYPE=debug
/home/user> export MALLOCDEBUG=report_allocations

清單 2. 程序的輸出/home/user> ./stud 2>mal_dbg_stud
Student Name: Manish
Subjects # Maths  English
Student Name: Vaarun
Subjects # Chemistry  Physics
Student Name: Sandeep
Subjects # Biology  Maths
  ......
  ......
  ......
  ......
Student Name: Govind
Subjects # Physics  Biology
Student Name: Manish
Subjects # Maths  English
Current allocation report:
  Allocation #0: 0x2000EFE8
    Allocation size: 0x14
    Allocation traceback:
    0xD0371F64 malloc
    0xD0322194 init_malloc
    0xD0323224 malloc
    0x10000BE4 initialize_leaky
  Allocation #1: 0x20010FF0
    Allocation size: 0xA
    Allocation traceback:
    0xD0371F64 malloc
    0x10000C08 initialize_leaky
    0x10000DD4 main
    0x100001B4 __start
  Allocation #2: 0x20012FF0
    Allocation size: 0xA
    Allocation traceback:
    0xD0371F64 malloc
    0x10000C08 initialize_leaky
    0x10000DD4 main
    0x100001B4 __start
  ......
  ......
  ......
  ......
  Allocation #17: 0x20030FF0
    Allocation size: 0x10
    Allocation traceback:
    0xD0371F64 malloc
    0x100008F4 getnode
    0x10000B08 insert
    0x10000DDC main
  Allocation #18: 0x20032FF8
    Allocation size: 0x8
    Allocation traceback:
    0xD0371F64 malloc
    0x10000894 allocate_for_dbl_ptr
    0x10000910 getnode
    0x10000B08 insert
  Allocation #19: 0x20034FE8
    Allocation size: 0x14
    Allocation traceback:
    0xD0371F64 malloc
    0x10000A5C allocate_name
    0x10000B18 insert
    0x10000DDC main
  Allocation #22: 0x2003AFF0
    Allocation size: 0x10
    Allocation traceback:
    0xD0371F64 malloc
    0x100008F4 getnode
    0x10000B3C insert
    0x10000DDC main
  ......
  ......
  ......
  ......

MALLOCDEBUG 的輸出格式對於用戶來說並不是很友好。它只是為每個已分配且尚未釋放的內存塊打印 出調用 malloc 的函數堆棧。它還返回了內存塊的大小以及由 malloc 所返回的指針值。

為了使上面的輸出更容易理解,我們編寫了一個示例腳本。(請參見下載部分。請注意,這是一個適 用於與該示例程序具有類似輸出的示例腳本。)下面的清單 3 顯示了在對上面這些堆棧運行了該腳本之 後的輸出。

清單 3. 使用腳本解析 MALLOCDEBUG 的輸出/home/user> ./format_mallocdebug_op.ksh
Usage : ./stack.ksh stackfile
/home/katiyar/DW> ./format_mallocdebug_op.ksh ./mal_dbg_stud |
  tee ./mal_dbg_stud_formatted
Parsing output from debug malloc ...
Analyzed 50 stacks ...
main
insert
allocate_subjects
malloc
################################
220 bytes leaked in 22 Blocks
################################
main
insert
allocate_name
malloc
################################
220 bytes leaked in 11 Blocks
################################
__start
main
initialize_leaky
malloc
################################
190 bytes leaked in 16 Blocks
################################
main
insert
getnode
malloc
################################
176 bytes leaked in 11 Blocks
################################
insert
getnode
allocate_for_dbl_ptr
malloc
################################
88 bytes leaked in 11 Blocks
################################
initialize_leaky
malloc
init_malloc
malloc
################################
20 bytes leaked in 1 Blocks
################################

調查工作應從最大的洩漏著手。上面的第一個堆棧顯示出,main 調用了 insert,後者調用了 allocate_subjects。而 allocate_subjects 通過調用 malloc 來分配內存塊,並且這塊內存一直沒有釋 放。該腳本的輸出顯示,22 次獨立的分配總共產生了 220 個字節的洩漏。這表示您應該查看代碼,找出 在 allocate_subjects 函數中分配 10 個字節的數據的位置,並檢查是否釋放了其所有的實例。通過對 該程序的代碼進行仔細的分析,您可以找到出現問題並且應該釋放的內存塊。

可以對報告中的每個堆棧進行類似的分析,並對其進行修復。如果在運行該程序之前將 FREE_BLOCKS=1 環境變量導出到了 Shell,那麼對這個程序進行的修復將會立即生效。

清單 4. 釋放了通過 malloc 分配的內存塊之後的輸出/home/katiyar/DW> ./stud
Student Name: Manish
Subjects # Maths  English
Student Name: Vaarun
Subjects # Chemistry  Physics
Student Name: Sandeep
Subjects # Biology  Maths
  ......
  ......
  ......
  ......
Student Name: Govind
Subjects # Physics  Biology
Student Name: Manish
Subjects # Maths  English
Current allocation report:
Total allocations: 0.

結束語

當您的軟件運行在客戶的計算機上時,MALLOCDEBUG 是可供使用的 malloc 子系統監視工具之一。當 用戶在計算機上使用軟件的過程中出現 malloc 錯誤時,需要用戶提供 MALLOCDEBUG 日志,為了避免這 種情況,在將應用程序提交給客戶之前,使用 MALLOCDEBUG 對其進行測試是很有幫助的。我們希望本文 能夠為那些必須處理客戶計算機中的內存洩漏問題的開發人員和服務工程師提供有用的簡介。

本文配套源碼:http://www.bianceng.net/other/201212/746.htm

Copyright © Linux教程網 All Rights Reserved