S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

一种定位内存泄露的方法(Linux)

Posted on 2012-03-26 09:09 S.l.e!ep.¢% 阅读(730) 评论(0)  编辑 收藏 引用 所属分类: gdb


一种定位内存泄露的方法(Linux)
.
 分类: C/C++Linux2010-05-16 18:35611人阅读评论(0)收藏举报


目的:
 
本文是《一种定位内存泄露的方法(Solaris)》对应的Linux版本,调试器使用gdb。主要介绍实例部分。其他请见《一种定位内存泄露的方法(Solaris)》。
 
实例:
 
模拟new失败的程序:
 
#include <stdexcept>
 
class ABC
 
{
 
public:
 
        virtual ~ABC(){}
 
        int i;
 
        int j;
 
};
 
 
 
void f()
 
{
 
        for (int i = 0; i < 1000; ++i)
 
        {
 
                ABC* p = new ABC;
 
        }
 
        throw std::bad_alloc();
 
}
 
 
 
int main()
 
{
 
        f();
 
        return 0;
 
}
 
1) 编译运行此段代码。产生一个core文件
 
2) 用gdb打开这个core文件:
 
gdb a.out core
 
(gdb) run
 
Starting program: /test/new_fail/a.out

terminate called after throwing an instance of 'std::bad_alloc'
 
  what():  std::bad_alloc
 
 
 
Program received signal SIGABRT, Aborted.
 
0x00007ffff733f645 in raise () from /lib64/libc.so.6
 
(gdb) info proc
 
process 10683
 
cmdline = '/test/new_fail/a.out'
 
cwd = '/test/new_fail'
 
exe = '/test/new_fail/a.out'
 
(gdb) shell pmap 10683
 
10683: a.out
 
START               SIZE     RSS     PSS   DIRTY    SWAP PERM MAPPING
 
0000000000400000      4K      4K      4K      0K      0K r-xp /test/new_fail/a.out
 
0000000000600000      4K      4K      4K      4K      0K r--p /test/new_fail/a.out
 
0000000000601000      4K      4K      4K      4K      0K rw-p /test/new_fail/a.out
 
0000000000602000    132K     32K     32K     32K      0K rw-p [heap]
 
…(略)
 
Total:            11468K   1048K    684K    180K      0K
 
 
 
360K writable-private, 11108K readonly-private, 0K shared, and 1048K referenced
 
 
 
可以看到heap空间的起始地址是0x0000000000602000,共132K字节,即132*1024=135168字节。
 
3) 因为是64位应用程序,所以指针占8字节。所以需要遍历的指针个数为135168/8=16896。
 
4) 将结果输出到日志文件gdb.txt中:
 
(gdb) set height 0
 
(gdb) set logging on
 
Copying output to gdb.txt.
 
(gdb) x/16896a 0x0000000000602000
 
gdb.txt的内容:
 
0x602000:       0x0     0x21
 
0x602010:       0x400b30 <_ZTV3ABC+16>  0x0
 
0x602020:       0x0     0x21
 
0x602030:       0x400b30 <_ZTV3ABC+16>  0x0
 
….
 
5) 过滤gdb.txt:
 
awk '{print $2"/n"$3}' gdb.txt|c++filt|grep vtable>gdb_vtable.txt
 
gdb_vtable.txt的内容为:
 
<vtable for ABC+16>
 
<vtable for ABC+16>
 
<vtable for ABC+16>
 
<vtable for ABC+16>
 
….
 
6) 将gdb_vtable.txt的内容导入到SQLServer中(如果记录不多,可以用Excel代替)。表名为gdb_vtable,第一列Col001为符号。对其分组求和:
 
select Col001, count(1) quantity from gdb_vtable
 
group by Col001
 
order by quantity desc
 
结果为:
 
Col001                                                                                    quantity
 
<vtable for ABC+16>                                                              1000
 
<vtable for std::bad_alloc@@GLIBCXX_3.4+16>                1
 
可知core里有1000个ABC,遍历使用ABC的代码,可知存在泄漏。


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理