程序中記憶體洩露檢測—— pmap
轉自:https://blog.csdn.net/licanhua/article/details/6983534
效能測試的一項重要工作就是檢查有沒有記憶體洩露。linux下通過top/free/pmap/ps,會提供許多關於記憶體分配的資訊,如top裡面的VIRT,RSS,SWAP,VSZ,RES,SHR等等,到底哪些引數能夠用來檢測memory leak呢?雖然baidu,google很方便,但是一直沒有找到一個令人信服的答案。這些天一直在研究,結合我在以往實際工作中的一些經驗,在此做一個總結:
1,首先使用sar/top/free在系統級確定是否有記憶體洩露。如有,可以從top輸出確定哪一個process。
2,pmap/top/ps工具是能幫助確定process是否有memory leak。確定memory leak的原則:
A)VIRT/VSZ或者writeable/private (‘pmap –d’輸出)如果在做重複的操作過程中一直保持穩定增長,那麼一定有記憶體洩露。
B) RSS只能作為參考,不能用來確定是否有記憶體洩露。
C) 在performance testing過程中,前面一段時間的記憶體增長不能用來確定記憶體洩露。因為最初系統需要申請一些記憶體來處理traffic。如果記憶體在短期就增長數G或者在系統穩定後還在持續增長,那就需要分析了。在我的工作中,一般前面半個小時的記憶體增長我都忽略。
E)多次申請分配的地址空間可能不連續。在virtual address中有多個[anon]段。 Here 1M was alloated to000000001b56a000 and00002ac25a77c000.
000000001b56a00011561212 rw---[ anon ]
00002ac25a77c00010401616 rw---[ anon ]
以下的測試可以證明以上的推論。
示例程式碼:
- int global_i_init=0;
- static int static_global_j=11;
- int global_k;
- int main () {
- int tmp;
- printf ("global_i_init: 0x%lx\n"
- printf ("global_k non_init : 0x%lx\n",&global_k );
- printf ("static_global_j : 0x%lx\n",&static_global_j );
- printf ("stack i : 0x%lx\n",&tmp );
- getchar (); // step2
- char *x= new char[100*1024];
- printf ("data allocate 100k @0x%lx\n", x);
- getchar(); // step3
- char *x2= new char[1024*1024];
- printf ("data allocate 1M [email protected]%lx\n", x2);
- getchar(); // step4
- printf ("data write at x2[1024*1024-1] ");
- x2[1024*1024-1]=0;
- getchar(); // step5
- printf ("data read at x2 ");
- int j;
- for (int i=0;i<1024*1024; i++)
- j=x2[i];
- getchar (); // step6
- printf ("delete x2");
- delete x2;
- getchar (); //step 7
- printf ("delete x");
- delete x;
- getchar(); //step8
- x2= new char[1024*1024];
- printf ("data allocate 1M [email protected]%lx\n", x2);
- getchar ();
- }
程式輸出:
XX48-0-0-1:/root-# ./a.out
global_i_init: 0x500cc0
global_k non_init : 0x500cc4
static_global_j : 0x500cb8
stack i : 0x7fff0120ab5c
data allocate 100k @0x1b56a010
data allocate 1M [email protected]
data write at x2[1024*1024-1]
data read at x2
delete x2
delete x
data allocate 1M [email protected]
pmap -d 輸出:
mapped | writeable/private: | shared | ||
STEP 1 | init | 19616K | 236K | 0 |
STEP 2 | new 100k | 19848K | 468K | 0 |
STEP 3 | new 1M | 20876K | 1496K | 0 |
STEP 4 | write 1 byte | 20876K | 1496K | 0 |
STEP 5 | read 1M | 20876K | 1496K | 0 |
STEP 6 | delete 1M | 19848K | 468K | 0 |
STEP 7 | delete 100k | 19848K | 468K | 0 |
STEP 8 | new 1M | 20772K | 1392K | 0 |
pmap -d 結論:
1, mapped 和writeable/private 能夠反映記憶體的變化.
2, delete 和free 不能在 mapped 和writeable/private 立即反映出來,比方刪除100k就沒有變化.
pmap -x output:
Total kbytes | RSS | Dirty | ||
STEP 1 | init | 19616 | 912 | 124 |
STEP 2 | new 100k | 19848 | 976 | 140 |
STEP 3 | new 1M | 20876 | 980 | 144 |
STEP 4 | write 1 byte | 20876 | 984 | 148 |
STEP 5 | read 1M | 20876 | 2004 | 148 |
STEP 6 | delete 1M | 19848 | 976 | 140 |
STEP 7 | delete 100k | 19848 | 980 | 140 |
STEP 8 | new 1M | 20772 | 984 | 144 |
Address | kbytes | RSS | Dirty | ||
STEP 1 | init | ||||
STEP 2 | new 100k | 000000001b56a000 | 232 | 8 | 8 |
STEP 3 | new 1M | 000000001b56a000 | 232 | 8 | 8 |
STEP 4 | write 1 byte | 000000001b56a000 | 232 | 8 | 8 |
STEP 5 | read 1M | 000000001b56a000 | 232 | 8 | 8 |
STEP 6 | delete 1M | 000000001b56a000 | 232 | 8 | 8 |
STEP 7 | delete 100k | 000000001b56a000 | 232 | 8 | 8 |
STEP 8 | new 1M | 000000001b56a000 | 1156 | 12 | 12 |
Address | kbytes | RSS | Dirty | ||
STEP 1 | init | 00002ac25a77c000 | 12 | 12 | 12 |
STEP 2 | new 100k | 00002ac25a77c000 | 12 | 12 | 12 |
STEP 3 | new 1M | 00002ac25a77c000 | 1040 | 16 | 16 |
STEP 4 | write 1 byte | 00002ac25a77c000 | 1040 | 20 | 20 |
STEP 5 | read 1M | 00002ac25a77c000 | 1040 | 1040 | 20 |
STEP 6 | delete 1M | 00002ac25a77c000 | 12 | 12 | 12 |
STEP 7 | delete 100k | 00002ac25a77c000 | 12 | 12 | 12 |
STEP 8 | new 1M | 00002ac25a77c000 | 12 | 12 | 12 |
pmap -x 結論:
1, 儘管你已經呼叫了 new分配記憶體(step 3), 但是 OS不一定一下把所有的page都分配。本例中只有對那一塊已經分配記憶體進行讀 (STEP5)或者寫(STEP4) 的時候才提交實際記憶體。
pmap -x:
2, 多次相同的new操作可能在不同的[anon]虛擬地址空間分配。本例中第一個1M分配在00002ac25a77c000, 而第二個1M跑到000000001b56a000。中間跨度很大。
最終pmap -d:
Address Kbytes Mode Offset Device Mapping
0000000000400000 4 r-x-- 0000000000000000 008:00001 a.out
0000000000500000 4 rw--- 0000000000000000 008:00001 a.out
000000001b56a000 1156 rw--- 000000001b56a000 000:00000 [ anon ]
0000003677000000 112 r-x-- 0000000000000000 008:00001 ld-2.5.so
000000367721c000 4 r---- 000000000001c000 008:00001 ld-2.5.so
000000367721d000 4 rw--- 000000000001d000 008:00001 ld-2.5.so
0000003677400000 1336 r-x-- 0000000000000000 008:00001 libc-2.5.so
000000367754e000 2048 ----- 000000000014e000 008:00001 libc-2.5.so
000000367774e000 16 r---- 000000000014e000 008:00001 libc-2.5.so
0000003677752000 4 rw--- 0000000000152000 008:00001 libc-2.5.so
0000003677753000 20 rw--- 0000003677753000 000:00000 [ anon ]
0000003677c00000 520 r-x-- 0000000000000000 008:00001 libm-2.5.so
0000003677c82000 2044 ----- 0000000000082000 008:00001 libm-2.5.so
0000003677e81000 4 r---- 0000000000081000 008:00001 libm-2.5.so
0000003677e82000 4 rw--- 0000000000082000 008:00001 libm-2.5.so
0000003678c00000 52 r-x-- 0000000000000000 008:00001 libgcc_s-4.1.2-20080825.so.1
0000003678c0d000 2048 ----- 000000000000d000 008:00001 libgcc_s-4.1.2-20080825.so.1
0000003678e0d000 4 rw--- 000000000000d000 008:00001 libgcc_s-4.1.2-20080825.so.1
0000003679400000 920 r-x-- 0000000000000000 008:00001 libstdc++.so.6.0.8
00000036794e6000 2044 ----- 00000000000e6000 008:00001 libstdc++.so.6.0.8
00000036796e5000 24 r---- 00000000000e5000 008:00001 libstdc++.so.6.0.8
00000036796eb000 12 rw--- 00000000000eb000 008:00001 libstdc++.so.6.0.8
00000036796ee000 72 rw--- 00000036796ee000 000:00000 [ anon ]
00002ac25a76f000 16 rw--- 00002ac25a76f000 000:00000 [ anon ]
00002ac25a77c000 12 rw--- 00002ac25a77c000 000:00000 [ anon ]
00007fff011f8000 84 rw--- 00007ffffffe9000 000:00000 [ stack ]
00007fff013c2000 12 r-x-- 00007fff013c2000 000:00000 [ anon ]
ffffffffff600000 8192 ----- 0000000000000000 000:00000 [ anon ]
mapped: 20772K writeable/private: 1392K shared: 0K
pmap -x
Address Kbytes RSS Dirty Mode Mapping
0000000000400000 4 4 0 r-x-- a.out
0000000000500000 4 4 4 rw--- a.out
000000001b56a000 1156 12 12 rw--- [ anon ]
0000003677000000 112 96 0 r-x-- ld-2.5.so
000000367721c000 4 4 4 r---- ld-2.5.so
000000367721d000 4 4 4 rw--- ld-2.5.so
0000003677400000 1336 284 0 r-x-- libc-2.5.so
000000367754e000 2048 0 0 ----- libc-2.5.so
000000367774e000 16 16 8 r---- libc-2.5.so
0000003677752000 4 4 4 rw--- libc-2.5.so
0000003677753000 20 16 16 rw--- [ anon ]
0000003677c00000 520 20 0 r-x-- libm-2.5.so
0000003677c82000 2044 0 0 ----- libm-2.5.so
0000003677e81000 4 4 4 r---- libm-2.5.so
0000003677e82000 4 4 4 rw--- libm-2.5.so
0000003678c00000 52 16 0 r-x-- libgcc_s-4.1.2-20080825.so.1
0000003678c0d000 2048 0 0 ----- libgcc_s-4.1.2-20080825.so.1
0000003678e0d000 4 4 4 rw--- libgcc_s-4.1.2-20080825.so.1
0000003679400000 920 404 0 r-x-- libstdc++.so.6.0.8
00000036794e6000 2044 0 0 ----- libstdc++.so.6.0.8
00000036796e5000 24 24 20 r---- libstdc++.so.6.0.8
00000036796eb000 12 12 12 rw--- libstdc++.so.6.0.8
00000036796ee000 72 8 8 rw--- [ anon ]
00002ac25a76f000 16 16 16 rw--- [ anon ]
00002ac25a77c000 12 12 12 rw--- [ anon ]
00007fff011f8000 84 12 12 rw--- [ stack ]
00007fff013c2000 12 4 0 r-x-- [ anon ]
ffffffffff600000 8192 0 0 ----- [ anon ]
---------------- ------ ------ ------
total kB 20772 984 144
相關推薦
程序中記憶體洩露檢測—— pmap
轉自:https://blog.csdn.net/licanhua/article/details/6983534效能測試的一項重要工作就是檢查有沒有記憶體洩露。linux下通過top/free/pmap/ps,會提供許多關於記憶體分配的資訊,如top裡面的VIRT,RSS,
Android記憶體洩露檢測工具和實際開發中遇到的記憶體洩露問題解析
介紹 記憶體洩露是平常開發中經常遇到的,有些時候稍不注意就會發生,而且還不易察覺,這就需要工具來幫助檢測。本文主要介紹記憶體檢測工具和我在開發中遇到的記憶體洩露問題和解決方案。 記憶體洩露的原理 具體的原理涉及到虛擬機器垃圾回收機制知識,這裡只為下文作
Windows系統中記憶體洩露與檢測工具及方法
寫C/C++,經常碰到記憶體洩漏,同事發給我的查詢方法,試過有效,記錄一下。1.檢測需要使用的工具:windbg工具。檢測前,需要先安裝windbg工具。安裝了該工具後,會在安裝目錄下有一個umdh工具。假設windbg安裝在以下目錄下:D:\Program Files\De
Linux核心的Kmemleak實現記憶體洩露檢測
1. Kmemleak的使用方法 a. 在uboot的bootarg中加入"kmemleak=on" b. 在.config中使能如下配置 CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK=y CONFIG_
Android Native記憶體洩露檢測(針對Android7.0)
1. 需要合入一個 Patch 2. 執行指令 adb root adb shell setprop libc.debug.malloc.program cameraserver adb shell setprop libc.debug.malloc.options “backt
linux下記憶體洩露檢測工具Valgrind介紹
一、工作中一個記憶體洩漏問題的解決過程: 問題背景:我司裝置上執行有多個程序,在裝置執行兩天後,程序jsman所佔用的記憶體達到了1200M bytes(通過ps -aux檢視)。 解決步驟: 確定裝置上的軟體版本,根據git的commit號資訊回退
DevPartner Studio Professional Edition 11 記憶體洩露檢測使用
DevPartner Studio Professional Edition含有靜態程式碼分析、錯誤檢測、效能、覆蓋率和記憶體分析以及效能專家功能,用於 Visual Studio 2012、Visual Studio 2010、Visual Studio 2008
精準 iOS 記憶體洩露檢測工具----MLeaksFinder
背景 平常我們都會用 Instrument 的 Leaks / Allocations 或其他一些開源庫進行記憶體洩露的排查,但它們都存在各種問題和不便,我們逐個來看這些工具的使用和存在的問題。 Leaks 先看看 Leaks,從蘋果的開發者文件裡可以看到,一個 app 的記憶體分三類:
Qt中記憶體洩露和半自動記憶體管理
Qt中幫程式設計師做了一些記憶體回收的事情,但正因為這些反而讓對此不熟悉的人會屢屢犯錯。 收錄一篇不錯的文章: 在C++中學習過程中,我們都知道: delete 和 new 必須 配對使用(一 一對應):delete少了,則記憶體洩露,多了麻煩更大。 Qt作為C++的庫
c++記憶體洩露檢測
// 以下程式碼在vs2013上面測試#include <stdlib.h> #include <crtdbg.h> // 在入口函式中包含 _CrtDumpMemoryLeaks(); // 即可檢測到記憶體洩露 typedef void* HObjec
Android native memory leak detect (Android native記憶體洩露檢測)
簡介 Android應用中,經常會有業務需要使用到Native實現。比如加密,音視訊播放等。也就是常見的二進位制檔案xxx.so 這部分程式碼,申請的記憶體不走Java Heap管理。那麼一旦發生記憶體洩露,無法使用匯出MAT來進行檢視。 本篇文章將講解如
Linux下利用Valgrind工具進行記憶體洩露檢測和效能分析
Valgrind通常用來成分析程式效能及程式中的記憶體洩露錯誤 一 Valgrind工具集簡紹 Valgrind包含下列工具: 1、memcheck:檢查程式中的記憶體問題,如洩漏、越界、非法指標等。 2、callgrind:檢測程式程式碼的執行
Visual C++ 記憶體洩露檢測工具(VLD)
簡述 C/C++ 程式越複雜,記憶體的管理顯得越重要,稍有不慎就會出現洩漏。如果記憶體洩漏不是很嚴重,在短時間內對程式不會有太大影響,這也使得記憶體洩漏問題有很強的隱蔽性,不易被發現。然而不管記憶體洩漏多麼輕微,當程式長時間執行時,其破壞力是驚人的 - 從效能
使用Visual Leak Detector for Visual C++ 捕捉記憶體洩露---Visual C++記憶體洩露檢測—VLD工具使用說明
以下經過測試: 使用Visual Leak Detector for Visual C++ 捕捉記憶體洩露 1、下載vlc 2、建立應用並配置 c/c++ -> General -> Additional Include Directories = C:\P
Linux程序佔用記憶體分析之pmap
檢視程序的記憶體映像資訊(report memory map of a process) # pmap 用法 pmap [options] PID [PID ...] 選項 Options: -x, --extended show
Windows/Linux下C/C++記憶體洩露檢測工具
一 Window下的記憶體洩露檢測(以VC++環境為例) 靈活自由是C語言的一大特色,但這個特色也難以避免的帶來一些副作用,比如記憶體洩露。眾所周知,記憶體洩露的問題比較複雜,程式正常執行時你看不出它有任何異常,但長時間執行或在特定條件下特定操作重複多次時,它才暴露出來。所
VS 2013記憶體洩露檢測的方法
例項: #include "stdafx.h" #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #else #define DEBUG_CLIENTBLOCK
Android NDK 記憶體洩露檢測
前言最近寫C++程式碼,老是擔心程式碼存在記憶體洩露,膽戰心驚的,Andorid中Java層程式碼記憶體洩露可以藉助leakcanary進行檢測;找了一番,找到了PC上C++上的記憶體洩露檢測庫LeakTracer,於是再找了下,找到了Android上的移植版。首先建立一個專案,在根目錄下建立thirdpar
iOS-記憶體洩露檢測工具(MLeaksFinder)
MLeaksFinder MLeaksFinder helps you find memory leaks in your iOS apps at develop time. It can automatically find leaks in UIVi
Linux C 程式設計記憶體洩露檢測工具(二):memwatch
Memwatch簡介 在三種檢測工具當中,設定最簡單的算是memwatch,和dmalloc一樣,它能檢測未釋放的記憶體、同一段記憶體被釋放多次、位址存取錯誤及不當使用未分配之記憶體區域。請往http://www.linkdata.se/sourcecode.html下載最