1. 程式人生 > >程序中記憶體洩露檢測—— pmap

程序中記憶體洩露檢測—— 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或者在系統穩定後還在持續增長,那就需要分析了。在我的工作中,一般前面半個小時的記憶體增長我都忽略。

D) 我們會發現,VSZ或者其他增長以後即使你呼叫了free/delete也不一定會減少或者回復到初始水平。這是系統的正常行為,釋放的那一部份空間馬上就能重用。

E)多次申請分配的地址空間可能不連續。在virtual address中有多個[anon]段。 Here 1M was alloated to000000001b56a000    and00002ac25a77c000.

000000001b56a00011561212 rw---[ anon ]

00002ac25a77c00010401616 rw---[ anon ]

以下的測試可以證明以上的推論。

示例程式碼:

  1. #include "stdio.h"
  2. int global_i_init=0;
  3. static int static_global_j=11;
  4. int global_k;
  5. int main () {
  6. int tmp;
  7. printf ("global_i_init: 0x%lx\n"
    ,&global_i_init );
  8. printf ("global_k non_init : 0x%lx\n",&global_k );
  9. printf ("static_global_j : 0x%lx\n",&static_global_j );
  10. printf ("stack i : 0x%lx\n",&tmp );
  11. getchar (); // step2
  12. char *x= new char[100*1024];
  13. printf ("data allocate 100k @0x%lx\n", x);
  14. getchar(); // step3
  15. char *x2= new char[1024*1024];
  16. printf ("data allocate 1M [email protected]%lx\n", x2);
  17. getchar(); // step4
  18. printf ("data write at x2[1024*1024-1] ");
  19. x2[1024*1024-1]=0;
  20. getchar(); // step5
  21. printf ("data read at x2 ");
  22. int j;
  23. for (int i=0;i<1024*1024; i++)
  24. j=x2[i];
  25. getchar (); // step6
  26. printf ("delete x2");
  27. delete x2;
  28. getchar (); //step 7
  29. printf ("delete x");
  30. delete x;
  31. getchar(); //step8
  32. x2= new char[1024*1024];
  33. printf ("data allocate 1M [email protected]%lx\n", x2);
  34. getchar ();
  35. }

程式輸出:

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 輸出:

mappedwriteable/private:shared
STEP 1init19616K236K0
STEP 2new 100k19848K468K0
STEP 3new 1M20876K1496K0
STEP 4write 1 byte20876K1496K0
STEP 5read 1M20876K1496K0
STEP 6delete 1M19848K468K0
STEP 7delete 100k19848K468K0
STEP 8new 1M20772K1392K0

pmap -d 結論:

1, mapped 和writeable/private 能夠反映記憶體的變化.

2, delete 和free 不能在 mapped 和writeable/private 立即反映出來,比方刪除100k就沒有變化.


pmap -x output:

Total kbytesRSSDirty
STEP 1init19616912124
STEP 2new 100k19848976140
STEP 3new 1M20876980144
STEP 4write 1 byte20876984148
STEP 5read 1M208762004148
STEP 6delete 1M19848976140
STEP 7delete 100k19848980140
STEP 8new 1M20772984144
AddresskbytesRSSDirty
STEP 1init
STEP 2new 100k000000001b56a00023288
STEP 3new 1M000000001b56a00023288
STEP 4write 1 byte000000001b56a00023288
STEP 5read 1M000000001b56a00023288
STEP 6delete 1M000000001b56a00023288
STEP 7delete 100k000000001b56a00023288
STEP 8new 1M000000001b56a00011561212
AddresskbytesRSSDirty
STEP 1init00002ac25a77c000121212
STEP 2new 100k00002ac25a77c000121212
STEP 3new 1M00002ac25a77c00010401616
STEP 4write 1 byte00002ac25a77c00010402020
STEP 5read 1M00002ac25a77c0001040104020
STEP 6delete 1M00002ac25a77c000121212
STEP 7delete 100k00002ac25a77c000121212
STEP 8new 1M00002ac25a77c000121212

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下載最