内存不符预期的不断上涨,可能的原因是内存泄漏,例如new出来的对象未进行delete就重新进行复制,使得之前分配的内存块被悬空,应用程序没办法访问到那部分内存,并且也没有办法释放;在C++中,STL容器都会有clear()方法并且伴随RAII原则对容器里元素进行清理,但除了STL还有可能是字符串不断地在进行累加,不断的分配出新的内存块存放增长的字符串。

cppzh 群 内看到讨论利用jemalloc对内存占用的调试,能够清楚的 dump 出内存的使用情况,便尝试了下。

安装

# 用于生成 pdf
yum -y install graphviz ghostscript wget https://github.com/jemalloc/jemalloc/archive/5.1.0.tar.gz
tar zxvf 5.1.0.tar.gz
cd jemalloc-5.1.0/
./autogen.sh
./configure --prefix=/usr/local/jemalloc-5.1.0 --enable-prof
make -j
make install

程序退出时的用例和检查

# run
MALLOC_CONF=prof_leak:true,lg_prof_sample:0,prof_final:true LD_PRELOAD=/usr/local/jemalloc-5.1.0/lib/libjemalloc.so.2 ./a.out # 查看内存占用情况
/usr/local/jemalloc-5.1.0/bin/jeprof a.out jeprof.34447.0.f.heap
> top

长时间运行-测试用例

对于长时间运行的程序,例如服务端程序通常不能够退出,jemalloc提供每增长指定大小进行一次内存dump。

下面这个例子mock长时间运行的程序,分别测试顺序容器(vector)和关联容器(map),string 和最基本的new,并且每100ms执行1000次,代表服务端的运行情况。

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <chrono>
#include <thread> int main() { std::vector<int> vec;
std::map<int, int> mp;
std::string s;
for (;;) {
for (int i = 0; i < 1000; ++i) {
vec.push_back(i);
mp[rand()] = i;
s += "xxxx";
new char[4];
}
std::this_thread::sleep_for(std::chrono::microseconds(100));
} return 0;
}

编译运行:

g++ test.cc -o a.out

将环境变量MALLOC_CONF设置为prof:true,lg_prof_interval:26使jemalloc开启prof并且每2^26字节(64M)大小进行一次dump,并且利用LD_PRELOAD 环境变量代替。

export MALLOC_CONF="prof:true,lg_prof_interval:26"
LD_PRELOAD=/usr/local/jemalloc-5.1.0/lib/libjemalloc.so.2 ./a.out [root@pwh c++]# ls -l -t
total 212
-rw-r--r-- 1 root root 5208 Dec 19 14:31 jeprof.17988.17.i17.heap
-rw-r--r-- 1 root root 5206 Dec 19 14:31 jeprof.17988.16.i16.heap
-rw-r--r-- 1 root root 5204 Dec 19 14:31 jeprof.17988.15.i15.heap
-rw-r--r-- 1 root root 5204 Dec 19 14:31 jeprof.17988.14.i14.heap
-rw-r--r-- 1 root root 5204 Dec 19 14:31 jeprof.17988.13.i13.heap
-rw-r--r-- 1 root root 5204 Dec 19 14:31 jeprof.17988.12.i12.heap
-rw-r--r-- 1 root root 5204 Dec 19 14:31 jeprof.17988.11.i11.heap
-rw-r--r-- 1 root root 5200 Dec 19 14:31 jeprof.17988.10.i10.heap
-rw-r--r-- 1 root root 5200 Dec 19 14:31 jeprof.17988.9.i9.heap
-rw-r--r-- 1 root root 5200 Dec 19 14:31 jeprof.17988.8.i8.heap
-rw-r--r-- 1 root root 5198 Dec 19 14:31 jeprof.17988.7.i7.heap
-rw-r--r-- 1 root root 5198 Dec 19 14:31 jeprof.17988.6.i6.heap
...

结果分析

由于是每隔一段内存大小进行的dump,每个文件都是内存的片段信息,利用--base指定从哪一份heap文件开始分析。

$ /usr/local/jemalloc-5.1.0/bin/jeprof a.out --base=jeprof.17988.0.i0.heap  jeprof.17988.17.i17.heap
$ /usr/local/jemalloc-5.1.0/bin/jeprof a.out --base=jeprof.17988.0.i0.heap jeprof.17988.17.i17.heap
Using local file a.out.
Argument "MSWin32" isn't numeric in numeric eq (==) at /usr/local/jemalloc-5.1.0/bin/jeprof line 5123.
Argument "linux" isn't numeric in numeric eq (==) at /usr/local/jemalloc-5.1.0/bin/jeprof line 5123.
Using local file jeprof.17988.17.i17.heap.
Welcome to jeprof! For help, type 'help'.
(jeprof) top
Total: 1002.5 MB
754.5 75.3% 75.3% 754.5 75.3% __gnu_cxx::new_allocator::allocate@4031fc
124.0 12.4% 87.6% 124.0 12.4% __gnu_cxx::new_allocator::allocate@402fac
124.0 12.4% 100.0% 124.0 12.4% std::__cxx11::basic_string::_M_mutate
0.0 0.0% 100.0% 1002.5 100.0% __libc_start_main
0.0 0.0% 100.0% 1002.5 100.0% _start
0.0 0.0% 100.0% 1002.5 100.0% main
0.0 0.0% 100.0% 754.5 75.3% std::_Rb_tree::_M_create_node
0.0 0.0% 100.0% 754.5 75.3% std::_Rb_tree::_M_emplace_hint_unique
0.0 0.0% 100.0% 754.5 75.3% std::_Rb_tree::_M_get_node
0.0 0.0% 100.0% 124.0 12.4% std::_Vector_base::_M_allocate # 导出为 pdf
/usr/local/jemalloc-5.1.0/bin/jeprof --pdf a.out --base=jeprof.17988.0.i0.heap jeprof.17988.17.i17.heap > a.pdf

统计内存使用情况

取了新的一段内存区间将其导出为pdf后,总共分配使用718MB内存,其中在map的[]的操作符重载函数中占用了514.5MB,为string分配了60MB,为vector分配了60MB,而最基础的new char[4]的调用栈是停留在main()中,所以main()也占用了84MB,得到的数据和Total MB(718.5MB)吻合。

ref

利用Jemalloc进行内存泄漏的调试的更多相关文章

  1. [轉]Android的内存泄漏和调试

    一. Android的内存机制 Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似.程序员通过new为对象分配内存,所有对象在java堆内分配空间:然而对象的 ...

  2. 【VS开发】关于内存泄漏的调试

    没想到造成泄漏的原因是由于保存数据的线程因为事件阻塞在那里,此时要关闭OnClose的时候,这个挂起的线程爆出了内存泄漏,所以在关闭窗口之前,需要SetEvent(m_hSaveDataEvent); ...

  3. Android性能优化之利用LeakCanary检测内存泄漏及解决办法

    前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...

  4. Android内存泄漏分析及调试

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/13017999 此文承接我的另一篇文章:Android进程的内存管理分析 首先 ...

  5. VC使用CRT调试功能来检测内存泄漏

    信息来源:csdn     C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:“最大的长处也可能成为最大的弱点”,那么 C/C++ 应用程序正好印证了这句话.在 C/C+ ...

  6. (转)Android内存泄漏分析及调试

      http://blog.csdn.net/gemmem/article/details/13017999 此文承接我的另一篇文章:Android进程的内存管理分析  首先了解一下dalvik的Ga ...

  7. python 内存泄漏调试

    Python应用程序内存泄漏的调试 Quake Lee quakelee@geekcn.org 新浪网技术(中国)有限公司 Sina Research & Development Python ...

  8. C/C++内存泄漏及检测 转

    C/C++内存泄漏及检测 2011-02-20 17:51 by 吴秦, 30189 阅读, 13 评论, 收藏, 编辑 “该死系统存在内存泄漏问题”,项目中由于各方面因素,总是有人抱怨存在内存泄漏, ...

  9. 【转】C/C++内存泄漏及检测

    “该死系统存在内存泄漏问题”,项目中由于各方面因素,总是有人抱怨存在内存泄漏,系统长时间运行之后,可用内存越来越少,甚至导致了某些服务失败.内存泄漏是最难发现的常见错误之一,因为除非用完内存或调用ma ...

随机推荐

  1. 【LeetCode】733. Flood Fill 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:DFS 方法二:BFS 日期 题目地址:ht ...

  2. python学习第二天:命令行模式和python交互模式

    命令行模式 安装完python开发环境和工具之后,在Windows开始菜单选择"命令提示符",就会进入到命令行模式: 或者都可以,然后 点击enter键,弹出下图中的窗口,即命令行 ...

  3. Reflection 基础知识(二)

    Proxy 定义 Proxy用于修改对象的某些行为,获取值,设置值等 let p = new Proxy(target, handler); target 用Proxy包装的目标对象(可以是任何类型的 ...

  4. 【MySQL作业】SELECT 数据查询——美和易思select 选择列表应用习题

    点击打开所使用到的数据库>>> 1.查询所有客户的地址和电话号码. SELECT address, phone FROM customer 2.查询所有商品的名称.种类和单价信息. ...

  5. MySQL数据操作与查询笔记 • 【第5章 MySQL 函数】

    全部章节   >>>> 本章目录 5.1 数学函数和控制流函数 5.1.1 数学函数 5.1.2 控制流函数 5.2 字符串函数 5.2.1 字符串函数介绍 5.2.2 字符串 ...

  6. Hadoop用户配置免密登陆

    Hadoop用户配置免密登陆, 参考其他免密配置方法自己总结的更简洁的步骤. 要实现A免密登陆B,需要把A生成的公钥放到B的对应目录下, 要实现ABC之间免密登陆,把3者的公钥汇总到一个文件中, 然后 ...

  7. Notepad++快速选中多行

    我们在编辑文章的时候, 通常需要选择多行连续的文本, 可以使用Shift+鼠标选择多行文本, 如果一次需要选择的文本太多, 比如选择10000到20000行之间的文本, 鼠标要拉好久,手一累一抖,又要 ...

  8. css 基础 字体和文本样式

    字体样式处理font-size:30px:// 设置字体大小 font-weight:700://设置粗体 font-sytle:italic; //设置文字斜体 font-family: 斜体,宋体 ...

  9. linux 之 误删openssl文件夹重装openssl

    背景 使用 scp.ssh 都报错 error while loading shared libraries: libcrypto.so.1.0.0: cannot open shared objec ...

  10. 学习git&github

    详细学习视频: 链接:https://pan.baidu.com/s/1Vub3YTo7uUUuGCJUCabBRQ 提取码:6q9x 一.git基本工作流程 我们先来理解下Git 工作区.暂存区和版 ...