1。 記憶體使用情況分析
1。1 系統總記憶體分析
透過cat /proc/meminfo,可用的物理記憶體=MemFree+Buffers+Cached。
MemTotal: 5933132 kB
MemFree: 4485932 kB
MemAvailable: 4822944 kB
Buffers: 122148 kB
Cached: 630048 kB
SwapCached: 0 kB
Active: 806136 kB
Inactive: 461288 kB
Active(anon): 516344 kB
Inactive(anon): 230112 kB
Active(file): 289792 kB
Inactive(file): 231176 kB
Unevictable: 32 kB
Mlocked: 32 kB
SwapTotal: 7999484 kB
SwapFree: 7999484 kB
Dirty: 204 kB
Writeback: 0 kB
AnonPages: 515264 kB
…
echo 3 > /proc/sys/vm/drop_caches,會清理系統的cache。
Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free。
1-to free pagecache, 2-to free dentries and inodes, 3-to free pagecache, dentries and inodes。
1。2 程序記憶體分析
cat /proc/{pid}/maps
2。1 記憶體洩露型別
1。
常發性記憶體洩漏
發生記憶體洩漏的程式碼會被多次執行到,每次被執行的時候都會導致一塊記憶體洩漏
2。
偶發性記憶體洩漏
發生記憶體洩漏的程式碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以測試環境和測試方法對檢測記憶體洩漏至關重要
3。
一次性記憶體洩漏
發生記憶體洩漏的程式碼只會被執行一次,或者由於演算法上的缺陷,導致總會有一塊且僅有一塊記憶體發生洩漏
4。
隱式記憶體洩漏
程式在執行過程中不停的分配記憶體,但是直到結束的時候才釋放記憶體。嚴格的說這裡並沒有發生記憶體洩漏,因為最終程式釋放了所有申請的記憶體。但是對於
一個伺服器程式,需要執行幾天,幾周甚至幾個月,不及時釋放記憶體也可能導致最終耗盡系統的所有記憶體
。所以,我們稱這類記憶體洩漏為隱式記憶體洩漏
2。2 常用記憶體洩露檢測工具
C/C++
1。 Valgrind: Debugging and profiling Linux programs, aiming at programs written in C and C++
2。 ccmalloc: Linux和Solaris下對C和C++程式的簡單的使用記憶體洩漏和malloc除錯庫
3。 LeakTracer: Linux、Solaris和HP-UX下跟蹤和分析C++程式中的記憶體洩漏
4。 Electric Fence: Linux分發版中由Bruce Perens編寫的malloc()除錯庫
5。 Leaky: Linux下檢測記憶體洩漏的程式
6。 Dmalloc: Debug Malloc Library
7。 MEMWATCH: 由Johan Lindh編寫,是一個開放原始碼C語言記憶體錯誤檢測工具,主要是透過gcc的precessor來進行
8。 KCachegrind: A visualization tool for the profiling data generated by Cachegrind and Calltree
2。3 記憶體檢測原理
3。1 Linux核心記憶體洩漏檢測kmemleak
kmemlean提供了一種檢測核心記憶體洩露的方法,當記憶體物件沒有被釋放是,將其記錄在/sys/kernel/debug/kmemleak中。
3。1。1 使能kmemleak
CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=400 # CONFIG_DEBUG_KMEMLEAK_TEST is not set CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=n——————預設開啟
如果沒有開啟KMEMLEAK_FULL,則使用了精簡版。完整版比較耗記憶體,精簡版適合嵌入式除錯。
3。1。2 配置獲取kmemleak結果
引數配置:
off 禁用kmemleak(不可逆) stack=on 啟用任務堆疊掃描(default) stack=off 禁用任務堆疊掃描 scan=on 啟動自動記憶掃描執行緒(default) scan=off 停止自動記憶掃描執行緒 scan=
cat /sys/kernel/debug/kmemleak > kmemleak。txt
3。1。3 分析kmemleak洩漏情況
參考文件:
《kmemleak的使用》
《Linux Kernel Memory Leak Detection》
《Linux memory leak detection》
3。2 valgrind
Linux C/C++ Memory Leak Detection Tool
Linux 下幾款程式記憶體洩漏檢查工具
Linux下幾款C++程式中的記憶體洩露檢查工具
Linux 記憶體洩露檢測技巧
應用 Valgrind 發現 Linux 程式的記憶體問題
檢視程式記憶體空間兩種方法
一、檢視/proc/{pid}/maps檔案
二、pmap命令,原理上是一樣的
[root@info ~]# pmap 1013
什麼是記憶體洩漏
記憶體洩漏是指
程式動態申請的記憶體在使用完後沒有釋放,導致這段記憶體不能被作業系統回收再利用
。
例如這段程式,申請了4個位元組的空間但沒有釋放,有4個位元組的記憶體洩漏。
#include
using namespace std;
int main()
{
int *p = new int(1);
cout <<*p< return 0 } 隨著時間的推移,洩漏的記憶體越來越多,可用的記憶體越來越少,輕則效能受損,重則系統崩潰。 一般情況下, 發生記憶體洩漏時,重啟就可以回收洩漏的記憶體。但是對於linux,通常跑的是伺服器程式,不可以隨意重啟,在記憶體洩漏問題上就要格外小心 。 記憶體洩漏特點 難復現 — 要執行到足夠長的時間才會暴露。 難定位 — 出錯位置是隨機的,看不出與記憶體洩漏的程式碼有什麼聯絡。 最簡單的方法 為了避免寫出記憶體洩漏的程式,通常會有這樣的程式設計規範,要求我們在 寫程式時申請和釋放成對出現的 。因為每一次申請都意味著必須有一次釋放與它相對應。 基於這個特點,一種簡單的方法就是在 程式碼中統計申請和釋放的次數,如果申請和釋放的數量不同,就認為是記憶體洩漏了 。 #include “stdio。h” #include “stdlib。h” int malloc_count, free_count; void * my_malloc(int size) { malloc_count++; return malloc(size); } void my_free(void *p) { free_count++; free(p); } int main() { count = 0; int *p1 = (int *)my_malloc(sizeif(int)) int *p2 = (int *)my_malloc(sizeif(int)) printf(“%d, %d”, p1, p2); my_free(p1); if(malloc_count != free_count) printf(“memory leak!\n”); return 0 } 方法分析 優點: 直觀,容易理解,容易實現 缺點: 1。該方法要求執行結束時對執行中產生的列印分析才能知道結果。 2。該方法要求封裝所有申請和釋放空間的函式,並在呼叫的地方修改成呼叫封裝後的函式。雖然C中申請/釋放記憶體介面並不多,但是對於一個大型的專案,呼叫這些介面的地方卻是很多的,要全部替換是一個比較大的工作量。 3。只對C語言適用,不能應用於C++ 4。對於 所呼叫的庫不適用 。如果希望應用於庫,則要修改庫程式碼 5。只能檢測是否洩漏,卻沒有具體資訊,比如洩漏了多少空間 6。不能說明是哪一行程式碼引起了洩漏 Linux檢測程式記憶體洩漏 1。安裝valgrind: 這是一款開源的程式記憶體檢測工具,mtrace為記憶體分配函式(malloc, realloc, memalign,free)安裝hook函式。這些 hook函式記錄記憶體的申請和釋放的trace資訊 。 Valgrind詳解: Valgrind包括以下一些工具: 1。Memcheck:這是valgrind應用最廣泛的工具,一個重量級的記憶體檢查器,能夠給發現開發中絕大多數的記憶體錯誤使用的情況,比如:使用未初始化 2。callgrind:它主要用來檢查程式中函式中呼叫過程中出現的問題 3。cachegrind:它主要用來檢查程式中快取使用出現的問題 4。Helgrind:它主要用來檢查多執行緒中出現的競爭問題 5。Massif:它主要用來檢查程式中堆疊使用中出現的問題 6。Extension:可以使用core提供的功能,自己編寫特定的記憶體除錯工具 2。mtrace命令 man 3 mtrace 可以在man 手冊中檢視該函式 mtrace 也有對應的命令,其使用方式為: 一.將環境變數MALLOC_TRACE設定為所需輸出檔案的路徑名 二.在需要檢測的原始碼中引入mcheck。h標頭檔案 1.在分配記憶體之前呼叫mtrace(); ,一般在main函式的開頭呼叫 2.在結束檢測的地方呼叫muntrace(); ,一般在return之前呼叫 3.編譯程式時需要加上-g 選項 #include #include #include int main() { mtrace(); int *p = NULL; p =(int *)malloc(sizeof(int) * 1); //free(p);//未free,記憶體洩漏 muntrace(); return 0; } 4。記憶體洩漏資訊將在MALLOC_TRACE環境變數指定的檔案中報告,需要使用mtrace命令將資訊轉換。 Valgrind的最新版是3。11。0,它一般包含下列工具: 1。Memcheck 最常用的工具,用來檢測程式中出現的記憶體問題,所有對記憶體的讀寫都會被檢測到,一切對malloc()/free()/new/delete的呼叫都會被捕獲。所以,它能檢測以下問題: 對未初始化記憶體的使用; 讀/寫釋放後的記憶體塊; 讀/寫超出malloc分配的記憶體塊; 讀/寫不適當的棧中記憶體塊; 記憶體洩漏,指向一塊記憶體的指標永遠丟失; 不正確的malloc/free或new/delete匹配; memcpy()相關函式中的dst和src指標重疊。 2。Callgrind 和gprof類似的分析工具,但它對程式的執行觀察更是入微,能給我們提供更多的資訊。和gprof不同,它不需要在編譯原始碼時附加特殊選項,但加上除錯選項是推薦的。Callgrind收集程式執行時的一些資料,建立函式呼叫關係圖,還可以有選擇地進行cache模擬。在執行結束時,它會把分析資料寫 入一個檔案。callgrind_annotate可以把這個檔案的內容轉化成可讀的形式。 3。Cachegrind Cache分析器,它模擬CPU中的一級快取I1,Dl和二級快取,能夠精確地指出程式中cache的丟失和命中。如果需要,它還能夠為我們提供 cache丟失次數,記憶體引用次數,以及每行程式碼,每個函式,每個模組,整個程式產生的指令數。這對最佳化程式有很大的幫助。 4。Helgrind 它主要用來檢查多執行緒程式中出現的競爭問題。Helgrind尋找記憶體中被多個執行緒訪問,而又沒有一貫加鎖的區域,這些區域往往是執行緒之間失去同步的地 方,而且會導致難以發掘的錯誤。Helgrind實現了名為“Eraser”的競爭檢測演算法,並做了進一步改進,減少了報告錯誤的次數。不過,Helgrind仍然處於實驗階段。 5。Massif 堆疊分析器,它能測量程式在堆疊中使用了多少記憶體,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少記憶體的使用,在帶有虛擬記憶體的現代系統中,它還能夠加速我們程式的執行,減少程式停留在交換區中的機率。 此外,lackey和nulgrind也會提供。Lackey是小型工具,很少用到;Nulgrind只是為開發者展示如何建立一個工具。 1。3 原理 Memcheck 能夠檢測出記憶體問題, 關鍵在於其建立了兩個全域性表 。Valid-Value 表 對於程序的整個地址空間中的每一個位元組(byte),都有與之對應的 8 個 bits;對於CPU的每個暫存器,也有一個與之對應的bit向量。這些bits負責記錄該位元組或者暫存器值是否具有有效的、已初始化的值。 Valid-Address 表 對於程序整個地址空間中的每一個位元組(byte),還有與之對應的1個bit,負責記錄該地址是否能夠被讀寫。 檢測原理: 當要讀寫記憶體中某個位元組時,首先檢查這個位元組對應的 A bit。如果該A bit顯示該位置是無效位置,memcheck則報告讀寫錯誤。 核心(core)類似於一個虛擬的 CPU 環境,這樣當記憶體中的某個位元組被載入到真實的 CPU 中時,該位元組對應 的 V bit 也被載入到虛擬的 CPU 環境中。一旦暫存器中的值,被用來產生記憶體地址,或者該值能夠影響程式輸出,則 memcheck 會檢查對應的V bits,如果該值尚未初始化,則會報告使用未初始化記憶體錯誤。 2 安裝使用 2。1安裝 從官網http://www。valgrind。org下載最新版本(當前3。11) #tar xvf valgrind-3。11。1。tar。bz2 #cd valgrind-3。11。1 #。/configure ——prefix=/usr/local/valgrind——指定安裝目錄 #make #make install 2。2 命令介紹 用法:valgrind[options] prog-and-args [options]: 常用選項,適用於所有Valgrind工具 -tool= h –help 顯示幫助資訊。 -version 顯示valgrind核心的版本,每個工具都有各自的版本。 q –quiet 安靜地執行,只打印錯誤資訊。 v –verbose 更詳細的資訊, 增加錯誤數統計。 -trace-children=no|yes 跟蹤子執行緒? [no] -track-fds=no|yes 跟蹤開啟的檔案描述?[no] -time-stamp=no|yes 增加時間戳到LOG資訊? [no] -log-fd= -log-file= -log-file-exactly= -log-file-qualifier= 取得環境變數的值來做為輸出資訊的檔名。 [none] -log-socket=ipaddr:port 輸出LOG到socket ,ipaddr:port LOG資訊輸出: -xml=yes 將資訊以xml格式輸出,只有memcheck可用 -num-callers= -error-limit=no|yes 如果太多錯誤,則停止顯示新錯誤? [yes] -error-exitcode= -db-attach=no|yes 當出現錯誤,valgrind會自動啟動偵錯程式gdb。[no] -db-command= 適用於Memcheck工具的相關選項: -leak-check=no|summary|full 要求對leak給出詳細資訊? [summary] -leak-resolution=low|med|high how much bt merging in leak check [low] -show-reachable=no|yes show reachable blocks in leak check? [no] 在實際的專案中,最難纏的問題就是記憶體洩漏,當然還有panic之類的,記憶體洩漏分為兩部分使用者空間的和核心空間的。 我們就分別從這兩個層面分析一下。 使用者空間檢視記憶體洩漏和解決都相對簡單 。定位問題的方法和工具也很多相對容易。我們來看看。 1。 檢視記憶體資訊 cat /proc/meminfo、free、cat /proc/slabinfo等 2。 檢視程序的狀態資訊 top、ps、cat /proc/pid/maps/status/fd等 通常我們定位問題先在shell下ps檢視當前執行程序的狀態,嵌入式上可能顯示的資訊會少一些。 [root@localhost kthread]# ps auxw|more USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0。0 0。0 19396 1556 ? Ss May16 0:05 /sbin/init 我們可以很清晰看到VMZ和RSS的對比資訊。 VMZ就是這個程序申請的虛擬地址空間,而RSS是這個程序佔用的實際物理記憶體空間. 通常一個程序如果有記憶體洩露VMZ會不斷增大,相對的物理記憶體也會增加,如果是這樣一般需要檢查malloc/free是否匹配。根據程序ID我們可以檢視詳細的VMZ相關的資訊。例: 1。 root@hos-machine:~# cat /proc/1298/status 2。 Name: sshd 3。 State: S (sleeping) 4。 Tgid: 1298 5。 Ngid: 0 6。 Pid: 1298 7。 PPid: 1 8。 TracerPid: 0 9。 Uid: 0 0 0 0 10。 Gid: 0 0 0 0 11。 FDSize: 128 12。 Groups: 13。 NStgid: 1298 14。 NSpid: 1298 15。 NSpgid: 1298 16。 NSsid: 1298 17。 VmPeak: 65620 kB 18。 VmSize: 65520 kB 19。 VmLck: 0 kB 20。 VmPin: 0 kB 21。 VmHWM: 5480 kB 22。 VmRSS: 5452 kB 23。 VmData: 580 kB 24。 VmStk: 136 kB 25。 VmExe: 764 kB 26。 VmLib: 8316 kB 27。 VmPTE: 148 kB 28。 VmPMD: 12 kB 29。 VmSwap: 0 kB 30。 HugetlbPages: 0 kB 31。 Threads: 1 32。 SigQ: 0/7814 33。 SigPnd: 0000000000000000 34。 ShdPnd: 0000000000000000 35。 SigBlk: 0000000000000000 36。 SigIgn: 0000000000001000 37。 SigCgt: 0000000180014005 38。 CapInh: 0000000000000000 39。 CapPrm: 0000003fffffffff 40。 CapEff: 0000003fffffffff 41。 CapBnd: 0000003fffffffff 42。 CapAmb: 0000000000000000 43。 Seccomp: 0 44。 Cpus_allowed: ffffffff,ffffffff 45。 Cpus_allowed_list: 0-63 46。 Mems_allowed: 00000000,00000001 47。 Mems_allowed_list: 0 48。 voluntary_ctxt_switches: 1307 49。 nonvoluntary_ctxt_switches: 203 如果我們想檢視這個程序打開了多少檔案可以 [root@localhost kthread]# ls -l /proc/184172/fd/* | wc 214 2354 17293 順帶:(檢視程序開啟的所有檔案) [root@localhost kthread]# ls -l /proc/184172/fd/* |more lr-x————。 1 root root 64 Jul 10 16:35 /proc/184172/fd/0 -> /dev/null l-wx————。 1 root root 64 Jul 10 16:35 /proc/184172/fd/1 -> /usr/local/mm/mm。log lrwx————。 1 root root 64 Jul 10 16:35 /proc/184172/fd/10 -> socket:[13690382] lrwx————。 1 root root 64 Jul 10 16:35 /proc/184172/fd/100 -> socket:[13690549] 檢視程序詳細的記憶體對映資訊 cat /proc/7393/maps [root@localhost kthread]# cat /proc/184172/maps 00400000-00455000 r-xp 00000000 fd:05 1441820 /usr/local/mm/ms 00654000-00655000 rw-p 00054000 fd:05 1441820 /usr/local/mm/ms 00655000-00658000 rw-p 00000000 00:00 0 02205000-1a218000 rw-p 00000000 00:00 0 [heap] 3000600000-3000603000 r-xp 00000000 fd:00 143299 /lib64/libcom_err。so。2。1 3000603000-3000802000 ——-p 00003000 fd:00 143299 /lib64/libcom_err。so。2。1 我們看一下meminfo各個註釋:參考documentation/filesystem/proc。txt 1。 MemTotal: Total usable ram (i。e。 physical ram minus a few reserved bits and the kernel binary code) 2。 MemFree: The sum of LowFree+HighFree 3。 Buffers: Relatively temporary storage for raw disk blocks shouldn‘t get tremendously large (20MB or so) 4。 Cached: in-memory cache for files read from the disk (the pagecache)。 Doesn’t include 5。 SwapCached SwapCached: Memory that once was swapped out, is swapped back in but still also is in the swapfile (if memory is needed it 6。 doesn‘t need to be swapped out AGAIN because it is already in the swapfile。 This saves I/O) 7。 Active: Memory that has been used more recently and usually not reclaimed unless absolutely necessary。 8。 Inactive: Memory which has been less recently used。 It is more eligible to be reclaimed for other purposes 9。 HighTotal: 10。 HighFree: Highmem is all memory above ~860MB of physical memory Highmem areas are for use by userspace programs, or 11。 for the pagecache。 The kernel must use tricks to access this memory, making it slower to access than lowmem。 12。 LowTotal: 13。 LowFree: Lowmem is memory which can be used for everything that highmem can be used for, but it is also available for the 14。 kernel’s use for its own data structures。 Among many other things, it is where everything from the Slab is 15。 allocated。 Bad things happen when you‘re out of lowmem。 16。 SwapTotal: total amount of swap space available 17。 SwapFree: Memory which has been evicted from RAM, and is temporarily on the disk 18。 Dirty: Memory which is waiting to get written back to the disk 19。 Writeback: Memory which is actively being written back to the disk 20。 AnonPages: Non-file backed pages mapped into userspace page tables 21。 AnonHugePages: Non-file backed huge pages mapped into userspace page tables 22。 Mapped: files which have been mmaped, such as libraries 23。 Slab: in-kernel data structures cache 24。 SReclaimable: Part of Slab, that might be reclaimed, such as caches 25。 SUnreclaim: Part of Slab, that cannot be reclaimed on memory pressure 26。 PageTables: amount of memory dedicated to the lowest level of page tables。 27。 NFS_Unstable: NFS pages sent to the server, but not yet committed to stable storage 28。 Bounce: Memory used for block device “bounce buffers” 29。 WritebackTmp: Memory used by FUSE for temporary writeback buffers 30。 CommitLimit: Based on the overcommit ratio (’vm。overcommit_ratio‘), this is the total amount of memory currently available to 31。 be allocated on the system。 This limit is only adhered to if strict overcommit accounting is enabled (mode 2 in 32。 ’vm。overcommit_memory‘)。 33。 The CommitLimit is calculated with the following formula: CommitLimit = (’vm。overcommit_ratio‘ * Physical RAM) + Swap 34。 For example, on a system with 1G of physical RAM and 7G 35。 of swap with a `vm。overcommit_ratio` of 30 it would 36。 yield a CommitLimit of 7。3G。 37。 For more details, see the memory overcommit documentation in vm/overcommit-accounting。 38。 Committed_AS: The amount of memory presently allocated on the system。 The committed memory is a sum of all of the memory which 39。 has been allocated by processes, even if it has not been 40。 “used” by them as of yet。 A process which malloc()’s 1G 41。 of memory, but only touches 300M of it will only show up as using 300M of memory even if it has the address space 42。 allocated for the entire 1G。 This 1G is memory which has been “committed” to by the VM and can be used at any time 43。 by the allocating application。 With strict overcommit enabled on the system (mode 2 in ‘vm。overcommit_memory’), 44。 allocations which would exceed the CommitLimit (detailed above) will not be permitted。 This is useful if one needs 45。 to guarantee that processes will not fail due to lack of memory once that memory has been successfully allocated。 46。 VmallocTotal: total size of vmalloc memory area 47。 VmallocUsed: amount of vmalloc area which is used 48。 VmallocChunk: largest contiguous block of vmalloc area which is free 我們只需要關注幾項就ok。 buffers/cache/slab/active/anonpages Active= Active(anon) + Active(file) (同樣Inactive) AnonPages: Non-file backed pages mapped into userspace page tables\ buffers和cache的區別註釋說的很清楚了。 有時候不是記憶體洩露,同樣也會讓系統崩潰,比如cache、buffers等佔用的太多,開啟太多檔案 , 而等待系統自動回收是一個非常漫長的過程. 從proc目錄下的meminfo檔案瞭解到當前系統記憶體的使用情況彙總,其中 可用的物理記憶體=memfree+buffers+cached,當memfree不夠時,核心會透過回寫機制(pdflush執行緒)把cached和buffered記憶體回寫到後備儲存器 ,從而釋放相關記憶體供程序使用,或者透過手動方式顯式釋放cache記憶體 1。 drop_caches 2。 Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free。 3。 To free pagecache: 4。 echo 1 > /proc/sys/vm/drop_caches 5。 To free dentries and inodes: 6。 echo 2 > /proc/sys/vm/drop_caches 7。 To free pagecache, dentries and inodes: 8。 echo 3 > /proc/sys/vm/drop_caches 9。 As this is a non-destructive operation and dirty objects are not freeable, the user should run `sync`first 使用者空間記憶體檢測也可以透過mtrace來檢測用法也非常簡單 。 包括比較有名的工具valgrind、以及dmalloc、memwatch等。各有特點。 核心記憶體洩露 的 定位比較複雜 ,先判斷是否是核心洩露了,然後在具體定位什麼操作,然後再排查一些可疑的模組,核心記憶體操作基本都是kmalloc即透過slab/slub/slob機制,所以如果meminfo裡slab一直增長那麼很有可能是核心的問題。我們可以 更加詳細的檢視slab資訊cat /proc/slabinfo 如果支援slabtop更好,基本可以判斷核心是否有記憶體洩漏,並且是在操作什麼物件的時候發生的。 1。 cat /proc/slabinfo 2。 slabinfo - version: 2。1 3。 # name 4。 fuse_request 0 0 288 28 2 : tunables 0 0 0 : slabdata 0 0 0 5。 fuse_inode 0 0 448 18 2 : tunables 0 0 0 : slabdata 0 0 0 6。 fat_inode_cache 0 0 424 19 2 : tunables 0 0 0 : slabdata 0 0 0 7。 fat_cache 0 0 24 170 1 : tunables 0 0 0 : slabdata 0 0 0 在核心的配置中裡面已經支援了一部分memleak自動檢查的選項,可以開啟來進行跟蹤除錯。 這裡沒有深入的東西,算是拋磚引玉吧~。