linux檢測內存泄露
『壹』 linux內核內存泄露檢測
經常碰到系統跑著跑著一段時間內存滿了,出現內存泄漏的問題,系統軟體太龐大,這類問題又不好直接從源碼中分析,所以需要藉助工具來分析了,kmemleak就是這樣的一個工具。
在Kernel hacking中打開CONFIG_DEBUG_KMEMLEAK =y即使能了kmemleak,其實就是開了一個內核線程,該內核線程每10分鍾(默認值)掃描內存,並列印發現派耐新的未引用的對象的數量。kmemleak的原理其實就是通過kmalloc、vmalloc、kmem_cache_alloc等內存的分配,跟蹤其指針,連同其他的分配大小和堆棧跟蹤信息,存儲在PRIO搜索樹。如果存在相應的釋放函數調用跟蹤和指針,就會從kmemleak數據結構中移除塵毀春。下面我們看看具體的用法。
查看內核列印信息詳細過程如下:
1、掛載debugfs文件系統
mount -t debugfs nodev /sys/kernel/debug/
2、開啟內核自動檢測線程
echo scan > /sys/kernel/debug/kmemleak
3、查看列印信息
cat /sys/kernel/debug/kmemleak
4、清除內核檢測報告,新的內存泄露報告將重新寫入/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秒內自動記憶掃描,默認600s
scan 開啟內核掃描
clear 清除內存泄露報告
mp=<addr> 轉存信息對象在<addr>
通過「kmemleak = off」,也可以在啟動時禁用Kmemleak在內核命令行。在初始化kmemleak之前,內存的分配或釋放這些動作被存儲在余弊一個前期日誌緩沖區。這個緩沖區的大小通過配CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE設置。
『貳』 如何在linux下檢測內存泄漏
是不是說沒有一種內存檢查工具能夠在linux使用呢,也不是,像valgrind工具還是相當不錯的。他的下載地址是 下載一個valgrind 3.2.3 (tar.bz2) 工具,按照裡面的README提示,安裝後就可以使用這個工具來檢測內存泄露和內存越界等。這是一個沒有界面的內存檢測工具,安裝後,輸入valgrind ls -l 驗證一下該工具是否工作正常(這是README裡面的方法,實際上是驗證一下對ls -l命令的內存檢測),如果你看到一堆的信息說明你的工具可以使用了。 在編譯你的程序時,請設置-g參數,編譯出後使用如下的命令來判斷你的程序存在內存泄露: valgrind --tools=memcheck --leak-check=full yourProg在輸出信息中就會看到你的內存問題了。
『叄』 top怎麼查看內存泄露linux
看進程內存佔用情況啊
top -c之後按M
就是按內存佔用由大滑檔枯到小排序
如果內存佔用只有一兩GB或者在設置范圍內,一般就蠢做是沒有內存信洞泄露。
『肆』 如何在linux下檢測內存泄露
linux 可以用 valgrind 檢測內存泄漏
『伍』 linux下c++程序怎麼檢查代碼是否有內存泄露
編寫時,new的山慶變數沒有delete,會造成內存泄漏逗鉛握。
編寫時,訪問了未申請的地址,會造激派成內存泄漏。
運行時,有概率發生段錯誤這個錯誤,一般是內存泄漏導致。
還有其他情況,但是我一時半會想不起來了,就說這些吧。
『陸』 如何在linux下檢測內存泄漏
要想檢測內存泄漏,就必須對程序中的內存分配和釋放情況進行記錄,所能夠採取的辦法就是重載所有形式的operator new 和 operator delete,截獲 new operator 和 delete operator 執行過程中的內存操作信息。下面列出的就是重載形式
void* operator new( size_t nSize, char* pszFileName, int nLineNum )
void* operator new[]( size_t nSize, char* pszFileName, int nLineNum )
void operator delete( void *ptr )
void operator delete[]( void *ptr )
我們為 operator new 定義了一個新的版本,除了必須的 size_t nSize 參數外,還增加了文件名和行號,這里的文件名和行號就是這次 new operator 操作符被調用時所在的文件名和行號,這個信息將在發現內存泄漏時輸出,以幫助用戶定位泄漏具體位置。對於 operator delete,因為無法為之定義新的版本,我們直接覆蓋了全局的 operator delete 的兩個版本。
在重載的 operator new 函數版本中,我們將調用全局的 operator new 的相應的版本並將相應的 size_t 參數傳入,而後,我們將全局 operator new 返回的指針值以及該次分配所在的文件名和行號信息記錄下來,這里所採用的數據結構是一個 STL 的 map,以指針值為 key 值。當 operator delete 被調用時,如果調用方式正確的話(調用方式不正確的情況將在後面詳細描述),我們就能以傳入的指針值在 map 中找到相應的數據項並將之刪除,而後調用 free 將指針所指向的內存塊釋放。當程序退出的時候,map 中的剩餘的數據項就是我們企圖檢測的內存泄漏信息--已經在堆上分配但是尚未釋放的分配信息。
以上就是內存檢測實現的基本原理,現在還有兩個基本問題沒有解決:
1) 如何取得內存分配代碼所在的文件名和行號,並讓 new operator 將之傳遞給我們重載的 operator new。
2) 我們何時創建用於存儲內存數據的 map 數據結構,如何管理,何時列印內存泄漏信息。
先解決問題1。首先我們可以利用 C 的預編譯宏 __FILE__ 和 __LINE__,這兩個宏將在編譯時在指定位置展開為該文件的文件名和該行的行號。而後我們需要將預設的全局 new operator 替換為我們自定義的能夠傳入文件名和行號的版本,我們在子系統頭文件 MemRecord.h 中定義:
#define DEBUG_NEW new(__FILE__, __LINE__ )
而後在所有需要使用內存檢測的客戶程序的所有的 cpp 文件的開頭加入
#include "MemRecord.h"
#define new DEBUG_NEW
就可以將客戶源文件中的對於全局預設的 new operator 的調用替換為 new (__FILE__,__LINE__) 調用,而該形式的new operator將調用我們的operator new (size_t nSize, char* pszFileName, int nLineNum),其中 nSize 是由 new operator 計算並傳入的,而 new 調用點的文件名和行號是由我們自定義版本的 new operator 傳入的。我們建議在所有用戶自己的源代碼文件中都加入上述宏,如果有的文件中使用內存檢測子系統而有的沒有,則子系統將可能因無法監控整個系統而輸出一些泄漏警告。
再說第二個問題。我們用於管理客戶信息的這個 map 必須在客戶程序第一次調用 new operator 或者 delete operator 之前被創建,而且在最後一個 new operator 和 delete operator 調用之後進行泄漏信息的列印,也就是說它需要先於客戶程序而出生,而在客戶程序退出之後進行分析。能夠包容客戶程序生命周期的確有一人--全局對象(appMemory)。我們可以設計一個類來封裝這個 map 以及這對它的插入刪除操作,然後構造這個類的一個全局對象(appMemory),在全局對象(appMemory)的構造函數中創建並初始化這個數據結構,而在其析構函數中對數據結構中剩餘數據進行分析和輸出。Operator new 中將調用這個全局對象(appMemory)的 insert 介面將指針、文件名、行號、內存塊大小等信息以指針值為 key 記錄到 map 中,在 operator delete 中調用 erase 介面將對應指針值的 map 中的數據項刪除,注意不要忘了對 map 的訪問需要進行互斥同步,因為同一時間可能會有多個線程進行堆上的內存操作。
好啦,內存檢測的基本功能已經具備了。但是不要忘了,我們為了檢測內存泄漏,在全局的 operator new 增加了一層間接性,同時為了保證對數據結構的安全訪問增加了互斥,這些都會降低程序運行的效率。因此我們需要讓用戶能夠方便的 enable 和 disable 這個內存檢測功能,畢竟內存泄漏的檢測應該在程序的調試和測試階段完成。我們可以使用條件編譯的特性,在用戶被檢測文件中使用如下宏定義:
#include "MemRecord.h"
#if defined( MEM_DEBUG )
#define new DEBUG_NEW
#endif
當用戶需要使用內存檢測時,可以使用如下命令對被檢測文件進行編譯
g++ -c -DMEM_DEBUG xxxxxx.cpp
就可以 enable 內存檢測功能,而用戶程序正式發布時,可以去掉 -DMEM_DEBUG 編譯開關來 disable 內存檢測功能,消除內存檢測帶來的效率影響。
『柒』 Linux Kernel模塊內存泄露分析
假如通過「Free」查看內存幾乎耗盡,但通過 top/ps 命令卻看不出來用戶態應用凳凱程序佔用太多的內存空間, 那麼內核模塊可能發生了內存泄露
SLAB 是Linux內核中按照對象大小進行分配的內存分配器。
通過SLAB的信息好讓來查看內核模塊佔用的內存空間:
方法1. 查看meminfo文件
方法2. 查看slabinfo文件
一般查看slabinfo文件就足以,如果發現slabinfo中佔用內存過大,那基本可以斷定,內核模塊出現了內存泄露了
還有個命令 slabinfo 也是可以看,其實也是去讀 /proc/slabinfo 後可視化出來
Linux內核的Kmemleak實現內存泄露檢測
看看下面這個函數是哪裡導致的內存泄漏呢?
一眼可能不容易看出上面的有什麼問題,有kmalloc,有kfree 成對出現的。
問題正好出在 pr_debug 這個函數中的參數傳遞, 熟悉函數調用傳參的人應該會知道編譯器一般對參數的處理採用堆棧的方式,是一個先進後出的過程,這樣參數的執行一般是逆序的(由於編譯器實現的不同,這個過程不棗襪喚是確定的),這樣kfree會在kmalloc之前運行,導致每次運行都會泄漏一點內存。
Resolving Memory Leaks In Linux Kernel
Slab Allocator
Proc Info
Using Crash Debugger
『捌』 linux內存泄漏怎麼查
可以使用對應的軟體測試工具來查,如parasoft的c/c++等
『玖』 如何定位分析linux內存泄漏問題
1、閱讀源代碼及分析動態內存的使用
由於之前沒有做過類似的問題(純屬小白了,慘遭鄙視....),所以就想著通過自己去看代碼,查找裡面涉及到使用動態內存的代碼段去定位問題(現在想想,真是太幼稚了,大家見笑了...),但是自己還是去通過對源代碼跟蹤、分析,主要是對動態分配的內存(如malloc函數分配的內存)、一些文件描述符等進行跟蹤,分析在程序邏輯中對動態分配的內存有沒有手動進行釋放,打開的文件描述符有沒有關閉等這些代碼一點點的去分析,當然這也是熟悉代碼,了解的一個過程。
2、利用memwatch內存檢測工具對程序進行內存分析
Memwatch是一款C語言的內存檢測工具。memwatch使用它自己定義的功能函數取代所有在你的程序中用ANSI C定義的內存分配函數,memwatch的內存分配函數包含了所有的分配記錄信息。memwatch功能默認不是開啟的,除非定義了MEMWATCH,否則在代碼中不會跟蹤相關的內存使用情況。memwatch通常將它的數據寫入到memwatch.log文件中,它也可以被重定向.更多Linux操作知識,可以網路《Linux就該這么學》。
『拾』 嵌入式linux怎麼檢內存泄漏雨
檢測內存泄露主要有以下5種方法:
1、在需要內存泄漏檢查的代碼的開始調用void mtrace(void) (該函數在頭文件mcheck.h中有聲明)。mtrace為malloc等函數安裝hook,用於記錄內鄭返存分配信息.在需要內存泄漏檢查的代碼的結束調用void muntrace(void)。
注意: 一般情況下不要調用muntrace, 而讓程序自高叢游然結束. 因為可能有些釋放內存代碼要到muntrace之後才運行.
2、用debug模式編譯被檢查代碼(-g或-ggdb)。
3、設置環境變數MALLOC_TRACE為一文件名, 這一文件將存有內存分配信戚銷息。
4、運行被檢查程序, 直至結束或muntrace被調用。
5、用mtrace命令解析內存分配Log文件($MALLOC_TRACE)
(mtrace foo $MALLOC_TRACE, where foo is the executible name)
如果有內存泄漏,mtrace會輸出分配泄漏
內存的代碼位置,以及分配數量。