linux下檢測和定位記憶體洩漏位置的方法
gtest:http://code.google.com/p/googletest/,可以下載最新的程式碼。下載後,可以參考gtest-1.6.0\make\Makefile寫自己的Makefile。
程式記憶體的資訊(/proc/self/smaps):
VMSIZE: 15316 KB
RSS: 2560 KB total
1152 KB shared
428 KB private clean
980 KB private dirty
RSS(private dirty)最接近程式所使用的記憶體,特別是從heap分配的記憶體。
使用單元測試可以檢測記憶體洩漏。思路如下:
- 寫一個獲取當前記憶體的函式(獲取Private Dirty)。
- 函式開始執行時,記錄當前記憶體。
- 迴圈5萬/50萬/500萬次,執行某個目標函式(可能有洩漏的函式)。
- 每次迴圈都檢查記憶體,當記憶體增長了1M時,可以認定有記憶體洩漏。
當然目標函式是申請了記憶體,然後釋放記憶體,在生命週期結束時應該要釋放它的記憶體。
從頂級函式開始,或者從任意可能洩漏的函式開始,一直定位到記憶體洩漏的位置。可以使用utest中的mock來加快記憶體洩漏的速度。
在gtest-1.6.0同目錄下,寫Makefile如下:
# A sample Makefile for building Google Test and using it in user
# tests. Please tweak it to suit your environment and project. You
# may want to move it to your project's root directory.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.
# Please tweak the following variable definitions as needed by your
# project, except GTEST_HEADERS, which you can use in your own targets
# but shouldn't modify.
# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file.
GTEST_DIR = gtest-1.6.0
# Where to find user code.
USER_DIR = .
# Flags passed to the preprocessor.
CPPFLAGS += -I$(GTEST_DIR)/include
# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -O0
# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
TESTS = winlin_mem_leak_utest
# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
# House-keeping build targets.
all : $(TESTS)
clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o
# Builds gtest.a and gtest_main.a.
# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc
gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc
gtest.a : gtest-all.o
$(AR) $(ARFLAGS) [email protected] $^
gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) [email protected] $^
# Builds a sample test. A test should link with either gtest.a or
# gtest_main.a, depending on whether it defines its own main()
# function.
winlin_mem_leak_utest.o : $(USER_DIR)/winlin_mem_leak_utest.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/winlin_mem_leak_utest.cpp
winlin_mem_leak_utest : winlin_mem_leak_utest.o gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o [email protected]
同目錄下,寫winlin_mem_leak_utest.cpp,內容如下:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#include "gtest/gtest.h"
using namespace testing;
// less
#define AssertLess(a, b)\
EXPECT_TRUE(a < b); \
if(a >= b){ \
cout << "(" << #a << ")" \
<< "(" << a << ")" \
<< " < " \
<< "(" << #b << ")" \
<< "(" << b << ")" \
<< " failed!" \
<< endl; \
}
#define LoopAssertLess(exit, a, b)\
exit = (a >= b) ? true : exit; \
AssertLess(a, b);
// greater
#define AssertGreater(a, b)\
EXPECT_TRUE(a > b); \
if(a < b){ \
cout << "(" << #a << ")" \
<< "(" << a << ")" \
<< " > " \
<< "(" << #b << ")" \
<< "(" << b << ")" \
<< " failed!" \
<< endl; \
}
#define LoopAssertGreater(exit, a, b)\
exit = (a < b) ? true : exit; \
AssertGreater(a, b);
// the memory leak size, in KB.
// default is 1024(1MB), if the program leak 1MB, we think it's a leak!.
#define MemoryLeakSize 1024
// the biger this value, the more memory leak canbe detected(take more time also).
#define MemoryLeakDetectLoop 1000
// begin the memory leak test loop.
// usage: BeginLoopMemLeakTest()
// loop 1,000 times. (detect 1000byte leak to 1M).
#define BeginLoopMemLeakTest()\
BeginLoopMemLeakTestCount(MemoryLeakDetectLoop)
//
// loop 10,000 times. (detect 100byte leak to 1M).
#define BeginLoopMemLeakTest2() \
BeginLoopMemLeakTestCount(MemoryLeakDetectLoop*10)
//
// loop 50,000 times (detect 10byte leak to 1M).
#define BeginLoopMemLeakTest3()\
BeginLoopMemLeakTestCount(MemoryLeakDetectLoop*50)
//
// loop 500,000 times (detect 1byte leak to 1M).
#define BeginLoopMemLeakTest4()\
BeginLoopMemLeakTestCount(MemoryLeakDetectLoop*500)
//
// loop 5,000,000 times
#define BeginLoopMemLeakTest5()\
BeginLoopMemLeakTestCount(MemoryLeakDetectLoop*5000)
#define BeginLoopMemLeakTestCount(loop_count)\
MemView __a(0); \
bool __exit = false; \
int __alloc_once_size = 0;/*the normal alloc size.*/ \
for(int __i = 0; __i < loop_count && !__exit; __i++){ \
if(true){
// end the memory leak test loop.
// usage: EndLoopMemLeakTest()
// first time, the heap memory will totally free when pool delete it.
// second time, the memory will not free.
// third time, use the previous free memory.
// so here, if the memory is constant, we think it's ok and no memory leak.
#define EndLoopMemLeakTest()\
} \
MemView __c(0);\
if(__alloc_once_size == 0){ \
__alloc_once_size = __c.private_dirty - __a.private_dirty; \
} \
LoopAssertLess(__exit, __c.private_dirty - __a.private_dirty, __alloc_once_size + MemoryLeakSize);\
if(__exit){ \
cout << "leak detected loop #" << __i << endl;/**/ \
} \
}
#include "memview.cpp"
TEST(SimpleTest, MemoryLeakDetect){
BeginLoopMemLeakTest3()
new char[1]; // memory leak here
EndLoopMemLeakTest()
}
沒有洩漏的結果:
執行3萬次可以檢測到1個位元組的洩漏。結果如下:
可運用在實際專案中。
相關推薦
linux下檢測和定位記憶體洩漏位置的方法
gtest:http://code.google.com/p/googletest/,可以下載最新的程式碼。下載後,可以參考gtest-1.6.0\make\Makefile寫自己的Makefile。 程式記憶體的資訊(/proc/self/smaps): VMSIZE:
C++檢測和定位記憶體洩漏的技巧
在實際開發過程中專案中由於各方面原因,總是有人抱怨存在記憶體洩漏,系統長時間執行之後,可用記憶體越來越少,萇至導致了某些服務失敗。記憶體洩漏是最難發現的常見錯誤之一,因為除非用完記憶體或呼叫malloc失敗,否則都不會導致任何問題。實際上,使用C/C++這類沒有垃圾回收機制
linux下檢視cpu、記憶體和硬碟大小
轉載至:http://blog.sina.com.cn/s/blog_535aa0930100ltz8.html 查cpu #dmesg |grep -i xeon CPU0: Intel(R) Xeon(R) CPU E5520 @ 2.27G
如何在vs下linux下檢測記憶體洩露
1、記憶體洩漏簡介2、Windows平臺下的記憶體洩漏檢測 2.1、檢測是否存在記憶體洩漏問題2.2、定位具體的記憶體洩漏地方 3、Linux平臺下的記憶體洩漏檢測 4、總結 其實Windows、Linux下面的記憶體檢測都可以單獨開篇詳細介紹,方法和工
如何快速定位Android記憶體洩漏位置
如果所有的物件都可以被順利回收就沒有本文的誕生了,舉個簡單的例子,我們在開發中經常使用單例模式,單例的靜態特性導致其生命週期同應用一樣長。有時建立單例時如果我們需要Context物件,如果傳入的是Application的Context那麼不會有問題。如果傳入的是Activity的Context物件,那麼當
Linux中定位記憶體洩漏
1. 什麼是記憶體洩漏 記憶體洩漏是指堆記憶體的洩漏。堆記憶體是指程式從堆中分配的、大小任意的(記憶體塊的大小可以在程式執行期決定)、使用完後必須顯示釋放的記憶體。應用程式一般使用malloc、realloc、new等函式從堆中分配到一塊記憶體,使用完後,程式
Linux下檢視CPU、記憶體和硬碟型號及相關資訊命令
smartctl version 5.33 [i386-redhat-linux-gnu] Copyright (C) 2002-4 Bruce Allen Home page is http://smartmontools.sourceforge.net/ === START OF INFORMATION
linux下 bash_profile和bashrc區別
bash_profile和bashrc區別【.bash_profile 與 .bashrc 的區別】.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.【l
解決Linux 下server和client 通過TCP通訊:accept成功接收卻報錯的問題
ipv4 socket error 實例代碼 ... lis col argc 例子 今天在寫簡單的TCP通訊例子的時候,遇到了一個問題:server 和client能夠連接成功,並且client也能夠正常發送,但server就是接收不到,在網上搜索一番後,終於解決了問
如何在linux下檢測內存泄漏
nap 主程序 決定 行處理 sign cell 子進程 根據 參數重載 簡述 本文針對 linux 下的 C++ 程序的內存泄漏的檢測方法及其實現進行探討。其中包括 C++ 中的 new 和 delete 的基本原理,內存檢測子系統的實現原理和具體方法,以及內存泄漏檢測的
在Linux下安裝和卸載軟件
20180324一、安裝方法:rpm工具、yum工具、源碼包 1、rpm工具:由redhat公司開發; yum工具:是由Python開發的; 源碼包:由C語言開發,C語言是Linux上最標準的程序語言。 二、rpm工具的使用1、在虛擬機上掛載一CD到/mnt/目錄下: mount /dev/cdrom /m
Unix / Linux 下 nohup 和 & 的區別
http app 後來 gts -s 周期 能夠 不同 history 聲明:本文首發 簡單教程,網址為 https://www.twle.cn/t/332#reply0 就在剛剛回家的路上,被前同事奪命三連 call 呼喚解決一個問題:為啥放在 crontab 裏的命
Visual Studio中檢測記憶體洩漏的方法
Visual Studio中檢測記憶體洩漏的方法 #include <iostream> //可以定位到發生記憶體洩露 所在的檔案和具體那一行,用於檢測 malloc 分配的記憶體 #define _CRTDBG_MAP_ALLOC #include <s
linux下檢視cpu,記憶體,硬碟等硬體資訊的方法
說明:Linux下可以在/proc/cpuinfo中看到每個cpu的詳細資訊。但是對於雙核的cpu,在cpuinfo中會看到兩個cpu。常常會讓人誤以為是兩個單核的cpu。原文地址: http://www.hpboys.com/659.html一、linux CPU大小 [
Linux下at 和 crontab的基本運用以及臨時檔案基本管理
一、at的基本運用 在終端輸入watch -n 1 ls -R /mnt/ //監控檔案每秒檢視一次並以第歸的方式列出來 使用at命令制定延時任務
Linux下Tcl和expect 的安裝
背景介紹: 因搭建遊戲中心的測試環境,需要安裝兩個程式tcl8.4.13-src.tar.gz、expect-5.43.0.tar.gz 安裝方法: &n
Linux下profile和bashrc區別
Linux下profile和bashrc區別 1./etc/profile 用來設定系統環境引數,比如$PATH. 這裡面的環境變數是對系統內所有使用者生效的。 2./etc/bashrc 這個檔案設定系統bash shell相關的東西,對系統內所有使用者生效。只要
linux下檢視系統屬性 Linux下檢視和新增環境變數
Linux下檢視和新增環境變數 #檢視tomcat安裝路徑 sudo find / -name *tomcat* $PATH:決定了shell將到哪些目錄中尋找命令或程式,PATH的值是一系列目錄,當您執行一個程式時,Linux在這些目錄下進行搜尋編譯連結。 編輯你的 PATH 宣告
linux下poll和epoll核心原始碼剖析
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
根據記憶體洩漏位置新增斷點
_CrtSetBreakAlloc(XXX); XXX代表記憶體提示資訊中大括號中的數字。 Detected memory leaks! Dumping objects -> {98500} normal block at 0x05785AD0, 152 bytes long. Data: