日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux下几款C++程序中的内存泄露检查工具

發布時間:2024/1/23 linux 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux下几款C++程序中的内存泄露检查工具 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux下編寫C或者C++程序,有很多工具,但是主要編譯器仍然是gcc和g++。最近用到STL中的List編程,為了檢測寫的代碼是否會發現內存泄露,了解了一下相關的知識。

所有使用動態內存分配(dynamic memory allocation)的程序都有機會遇上內存泄露(memory leakage)問題,在Linux里有三種常用工具來檢測內存的泄露的情況,包括:

參見: http://elinux.org/Memory_Debuggers

偶然發現的內存泄露檢測工具比較

工具描述
valgrind一個強大開源的程序檢測工具
mtraceGNU擴展,用來跟蹤malloc,mtrace為內存分配函數(malloc, realloc, memalign, free)安裝hook函數
dmalloc用于檢查C/C++內存泄露(leak)的工具,即檢查是否存在直到程序運行結束還沒有釋放的內存,以一個運行庫的方式發布
memwatch和dmalloc一樣,它能檢測未釋放的內存、同一段內存被釋放多次、位址存取錯誤及不當使用未分配之內存區域
mpatrol一個跨平臺的C++內存泄露檢測器
dbgmem?

Electric Fence

?

?

?

1 被測程序


為了方便測試,,我們編寫了一個簡單的程序, 循環10次每次申請了一個100個字節的單元, 但是卻不釋放

2 valgrind


2.1 valgrind介紹


是不是說沒有一種內存檢查工具能夠在Linux使用呢,也不是,像開源的valgrind工具還是相當不錯的

  • Memcheck。這是valgrind應用最廣泛的工具,一個重量級的內存檢查器,能夠發現開發中絕大多數內存錯誤使用情況,比如:使用未初始化的內存,使用已經釋放了的內存,內存訪問越界等。這也是本文將重點介紹的部分。

  • Callgrind。它主要用來檢查程序中函數調用過程中出現的問題。

  • Cachegrind。它主要用來檢查程序中緩存使用出現的問題。

  • Helgrind。它主要用來檢查多線程程序中出現的競爭問題。

  • Massif。它主要用來檢查程序中堆棧使用中出現的問題。

  • Extension。可以利用core提供的功能,自己編寫特定的內存調試工具

主頁下載
valgrinddownloads

參照

Valgrind簡單用法

Unix下C程序內存泄漏檢測工具Valgrind安裝與使用

valgrind 的使用簡介

應用 Valgrind 發現 Linux 程序的內存問題

如何使用Valgrind memcheck工具進行C/C++的內存泄漏檢測

2.2 安裝


源碼安裝

到下載地址)下載最新版的valgrind,按照里面的README提示,安裝后就可以使用這個工具來檢測內存泄露和內存越界等

  • /configure

  • ?
  • make

  • ?
  • sudo make install

    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    當然也可以使用發行版的自帶的源中安裝

    sudo apt install valgrind
    • 1
    • 1

    這是一個沒有界面的內存檢測工具,安裝后,輸入 valgrind ls -l 驗證一下該工具是否工作正常(這是README里面的方法,實際上是驗證一下對ls -l命令的內存檢測),如果你看到一堆的信息說明你的工具可以使用了。

    2.3 使用說明


    Valgrind工具包包含多個工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。

    Memcheck

    最常用的工具,用來檢測程序中出現的內存問題,所有對內存的讀寫都會被檢測到,一切對malloc()/free()/new/delete的調用都會被捕獲。所以,Memcheck 工具主要檢查下面的程序錯誤

    內容描述
    使用未初始化的內存Use of uninitialised memory
    使用已經釋放了的內存Reading/writing memory after it has been free’d
    使用超過 malloc分配的內存空間Reading/writing off the end of malloc’d blocks
    對堆棧的非法訪問Reading/writing inappropriate areas on the stack
    申請的空間是否有釋放Memory leaks – where pointers to malloc’d blocks are lost forever
    malloc/free/new/delete申請和釋放內存的匹配Mismatched use of malloc/new/new [] vs free/delete/delete []
    src和dst的重疊Overlapping src and dst pointers in memcpy() and related functions

    這些問題往往是C/C++程序員最頭疼的問題,Memcheck在這里幫上了大忙。

    Callgrind

    和gprof類似的分析工具,但它對程序的運行觀察更是入微,能給我們提供更多的信息。和gprof不同,它不需要在編譯源代碼時附加特殊選項,但加上調試選項是推薦的。Callgrind收集程序運行時的一些數據,建立函數調用關系圖,還可以有選擇地進行cache模擬。在運行結束時,它會把分析數據寫入一個文件。callgrind_annotate可以把這個文件的內容轉化成可讀的形式。

    Cachegrind

    Cache分析器,它模擬CPU中的一級緩存I1,Dl和二級緩存,能夠精確地指出程序中cache的丟失和命中。如果需要,它還能夠為我們提供cache丟失次數,內存引用次數,以及每行代碼,每個函數,每個模塊,整個程序產生的指令數。這對優化程序有很大的幫助。

    Helgrind

    它主要用來檢查多線程程序中出現的競爭問題。Helgrind尋找內存中被多個線程訪問,而又沒有一貫加鎖的區域,這些區域往往是線程之間失去同步的地方,而且會導致難以發掘的錯誤。Helgrind實現了名為“Eraser”的競爭檢測算法,并做了進一步改進,減少了報告錯誤的次數。不過,Helgrind仍然處于實驗階段。

    Massif

    堆棧分析器,它能測量程序在堆棧中使用了多少內存,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少內存的使用,在帶有虛擬內存的現代系統中,它還能夠加速我們程序的運行,減少程序停留在交換區中的幾率。

    此外,lackey和nulgrind也會提供。Lackey是小型工具,很少用到;Nulgrind只是為開發者展示如何創建一個工具

    注意

    Valgrind不檢查靜態分配數組的使用情況

    Valgrind占用了更多的內存–可達兩倍于你程序的正常使用量

    如果你用Valgrind來檢測使用大量內存的程序就會遇到問題,它可能會用很長的時間來運行測試

    2.4 使用說明


    編譯程序

    g++ -g -o leak leak.c
    • 1
    • 1

    被檢測程序加入 –g -fno-inline 編譯選項保留調試信息, 否則后面的valgrind不能顯示到出錯行號。

    valgrind被設計成非侵入式的,它直接工作于可執行文件上,因此在檢查前不需要重新編譯、連接和修改你的程序。要檢查一個程序很簡單,只需要執行下面的命令就可以了。

    valgrind --tool=tool_name program_name
    • 1
    • 1

    比如我們要對ls -l命令做內存檢查,只需要執行下面的命令就可以了

    valgrind --tool=memcheck ls -l
    • 1
    • 1

    小提示?
    如果不知道有哪些參數, 可以先輸入valgrind –tool=, 然后狂按兩次tab, 會輸出linux系統的只能提示, 同樣,如果你輸入了valgrind –tool=mem再狂按兩次tab,linux系統會為你自動補全

    2.5 使用valgrind檢測Memcheck


    下面我們就可以用valgrind對我們的程序檢測leak

    valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes ./leak
    • 1
    • 1

    其中–leak-check=full 指的是完全檢查內存泄漏,

    –show-reachable=yes是顯示內存泄漏的地點,

    –trace-children=yes是跟入子進程。

    當程序正常退出的時候valgrind自然會輸出內存泄漏的信息原理:

    3 mtrace檢測內存泄露


    3.1 mtrace簡介


    在一般的linux發行版中,有一個自帶的工具可以很方便的替你完成這些事,這個工具就是mtrace.

    mtrace其實是GNU擴展函數,用來跟蹤malloc。

    mtrace為內存分配函數(malloc, realloc, memalign, free)安裝hook函數。這些hook函數記錄內存的申請和釋放的trace信息。?
    在程序中,這些trace信息可以被用來發現內存泄漏和釋放不是申請的內存。?
    當調用mtrace,mtrace會檢查環境變量MALLOC_TRACE。該環境變量應該包含記錄trace信息的文件路徑。如果文件可以被成功打開,它的大小被截斷為0。?
    如果MALLOC_TRACE沒有設置,或者設置的文件不可用或者不可寫,那么將不會安裝hook函數,mtrace不生效。

    詳細說明可參考man page:man 3 mtrace

    3.2 mtrace使用


    mtrace能監測程序是否內存泄露

    • 在程序的起始處包含頭文件
    #include <mcheck.h>
    • 1
    • 1
    • 更改環境變量:export MALLOC_TRACE=”mtrace.out”可以加入如下代碼
    setenv("MALLOC_TRACE", "mtrace.out", 1);
    • 1
    • 1
    • 調用函數mtrace()
    mtrace()
    • 1
    • 1
    • 編譯程序帶上 -g 選項
    gcc -g -c leak_mtrace.c -o leak_mtrace.o -std=gnu9x -Wall
    • 1
    • 1
    • 運行程序一次,盡量調用所有程序內的函數。這時調試信息就已經被寫入我們指定的mtrace.out文件中
    ./leak_mtrace
    • 1
    • 1
    • mtrace a.out mtrace.out查看內存監測情況
    mtrace a.out mtrace.out
    • 1
    • 1

    4 dmalloc


    dmalloc是一種用于檢查C/C++內存泄露(leak)的工具,即檢查是否存在直到程序運行結束還沒有釋放的內存,并且能夠精確指出在哪個源文件的第幾行。

    5 Linux內核的Kmemleak

    5.1 Kmemleak檢測工具介紹


    Kmemleak工作于內核態是內核自帶的內核泄露檢測工具, 其源代碼位于mm/kmemleak.c

    Kmemleak工作于內核態,Kmemleak 提供了一種可選的內核泄漏檢測,其方法類似于跟蹤內存收集器。當獨立的對象沒有被釋放時,其報告記錄在 /sys/kernel/debug/kmemleak中,Kmemcheck能夠幫助定位大多數內存錯誤的上下文。

    5.2 Kmemleak使用過程概述

    • 首先`CONFIG_DEBUG_KMEMLEAK在Kernel hacking中被使能.

    • 查看內核打印信息詳細過程如下:

    • 掛載debugfs文件系統?
      mount -t debugfs nodev /sys/kernel/debug/
    • 開啟內核自動檢測線程?
      echo scan > /sys/kernel/debug/kmemleak
    • 查看打印信息?
      cat /sys/kernel/debug/kmemleak
    • 清除內核檢測報告,新的內存泄露報告將重新寫入/sys/kernel/debug/kmemleak?
      echo clear > /sys/kernel/debug/kmemleak

    內存掃描參數可以進行修改通過向/sys/kernel/debug/kmemleak 文件寫入。 參數使用如下

  • off 禁用kmemleak(不可逆)

  • stack=on 啟用任務堆棧掃描(default)

  • stack=off 禁用任務堆棧掃描

  • scan=on 啟動自動記憶掃描線程(default)

  • scan=off 停止自動記憶掃描線程

  • scan=<secs> 設置n秒內自動記憶掃描

  • scan 開啟內核掃描

  • clear 清除內存泄露報告

  • dump=<addr> 轉存信息對象在<addr>

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    通過“kmemleak = OFF”,也可以在啟動時禁用Kmemleak在內核命令行。在初始化kmemleak之前,內存的分配或釋放這些動作被存儲在一個前期日志緩沖區。這個緩沖區的大小通過配CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE設置。

    5.3 Kmemleak動態檢測原理


    通過的kmalloc、vmalloc、kmem_cache_alloc等內存分配會跟蹤其指針,連同其他的分配大小和堆棧跟蹤信息,存儲在PRIO搜索樹。相應的釋放函數調用跟蹤和指針就會從kmemleak數據結構中移除。?
    分配的內存塊,被認為是獨立的,如果沒有指針指向它起始地址或塊的內部的任何位置,可以發現掃描內存(包括已保存的寄存器)。這意味著,有可能沒有辦法為內核通過所分配的地址傳遞塊到一個釋放函數,因此,該塊被認為是一個內存泄漏。

    掃描算法步驟:?
    1. 標記的所有分配對象為白色(稍后將剩余的白色物體考慮獨立的)

  • 掃描存儲器與所述數據片段和棧開始,檢查對地址的值存儲在PRIO搜索樹。如果一個白色的對象的指針被發現,該對象將被添加到灰名單

  • 掃描的灰色對象匹配的地址(一些白色物體可以變成灰色,并添加結束時的灰名單),直到黑色集結束

  • 剩下的白色物體被認為是獨立兒,并報告寫入/sys/kernel/debug/kmemleak。?
    一些分配的內存塊的指針在內核的內部數據結構和它們不能被檢測為孤兒。對避免這種情況,kmemleak也可以存儲的數量的值,指向一個內的塊的地址范圍內的地址,需要找到使塊不被認為是泄漏.

  • 5.4 kmem相關函數


    從kernel源代碼中的目錄include /linux/kmemleak.h中可查看函數原型的頭

    函數功能
    kmemleak_init初始化kmemleak
    kmemleak_alloc一個內存塊分配的通知
    kmemleak_alloc_percpu通知的一個percpu的內存塊分配
    kmemleak_free通知的內存塊釋放
    kmemleak_free_part通知釋放部分內存塊
    kmemleak_free_percpu一個percpu內存塊釋放的通知
    kmemleak_not_leak當不是泄露時,標記對象
    kmemleak_ignore當泄漏時不掃描或報告對象
    kmemleak_scan_area添加掃描區域內的內存塊
    kmemleak_no_scan不掃描的內存塊
    kmemleak_erase刪除一個指針變量的舊值
    kmemleak_alloc_recursive為kmemleak_alloc,只檢查遞歸
    kmemleak_free_recursive為kmemleak_free,只檢查遞歸

    總結

    以上是生活随笔為你收集整理的Linux下几款C++程序中的内存泄露检查工具的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。