linux 内存泄露检测 mtrace

17 篇文章 0 订阅

参考

mtrace

实验

1,写一个内存泄露的程序mt.c

#include <stdlib.h>
#include <mcheck.h>
int main()
{
        mtrace();
        int *a;
        a = malloc(sizeof(int));
        muntrace();
        return 0;
}

加上头文件
#include <mcheck.h>

然后在main()函数的开头加上
mtrace();

在main函数返回前加上
muntrace();

2,设置环境变量

MALLOC_TRACE=/home/stevewong/mtrace/mt.log

export MALLOC_TRACE

3,编译和运行程序

gcc mt.c -g mt.o

./mt.o

4,查看内存报告

mtrace mt.o mt.log

可以看到:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000d65460      0x4  at /home/stevewong/mtrace/mt.c:7

5,正确的程序mtfree.c


#include <stdlib.h>
#include <mcheck.h>
int main()
{
        mtrace();
        int *a;
        a = malloc(sizeof(int));
        if (a == NULL)
                return 1;
        free(a);
        muntrace();
        return 0;
}

6,编译,运行,查看内存泄露的情况

No memory leaks.

7,测试一下new的泄露是否能检测出来

#include <stdlib.h>
#include <new>
#include <mcheck.h>
using namespace std;
int main()
{
        mtrace();
        int *a;
        a = new int[10];
        muntrace();
        return 0;
}
Memory not freed:
-----------------
           Address     Size     Caller
0x000000000125d460     0x28  at 0x7fb584cc82e8

0x28就是40个字节,正好对应10个int。

再来看一个类的例子

include <stdlib.h>
#include <new>
#include <mcheck.h>
#include <iostream>
using namespace std;

class C
{
public:
        C()
        {
                cout << "new " << this << endl;
        }
        ~C()
        {
                cout << "delete " << this << endl;
        }
};

int main()
{
        mtrace();
        C *pc;
        pc = new C[10];
        cout << "addr of pc: " << pc << endl;
        cout << "size of pc: " << sizeof(pc) << endl;
        cout << "size of class C: "<< sizeof(C) << ", " << sizeof(pc[0]) << endl;
        //delete []pc;
        muntrace();
        return 0;
}

输出:

new 0x1eb9468
new 0x1eb9469
new 0x1eb946a
new 0x1eb946b
new 0x1eb946c
new 0x1eb946d
new 0x1eb946e
new 0x1eb946f
new 0x1eb9470
new 0x1eb9471
addr of pc: 0x1eb9468
size of pc: 8
size of class C: 1, 1

内存泄露检测

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000001eb9460     0x12  at 0x7fefd2c802e8

一个只有构造函数和析构函数的类占1个字节(构造函数和析构函数不占空间),10个空类10个字节,但是内存泄露检测显示size是0x12也就是18个字节,多出来的8个字节是?

使用gdb查看内存可以发现
display *((int*)0x1eb9460)

结果是10。说明这8个字节是存了数组的长度。

可以参考以下文章:
C++对象模型之简述C++对象的内存布局

如果只是delete了pc,没有delete整个对象数组呢?

#include <stdlib.h>
#include <new>
#include <mcheck.h>
#include <iostream>
using namespace std;

class C
{
public:
        C()
        {
                cout << "new " << this << endl;
        }
        ~C()
        {
                cout << "delete " << this << endl;
        }
};

int main()
{
        mtrace();
        C *pc;
        pc = new C[4];
        cout << "addr of pc: " << pc << endl;
        cout << "size of pc: " << sizeof(pc) << endl;
        cout << "size of class C: "<< sizeof(C) << ", " << sizeof(pc[0]) << endl;
        delete pc;
        muntrace();
        return 0;
}

只调用了一个析构函数,然后就出错了。

new 0x13d3468
new 0x13d3469
new 0x13d346a
new 0x13d346b
new 0x13d346c
new 0x13d346d
new 0x13d346e
new 0x13d346f
new 0x13d3470
new 0x13d3471
addr of pc: 0x13d3468
size of pc: 8
size of class C: 1, 1
delete 0x13d3468
*** Error in `./new': munmap_chunk(): invalid pointer: 0x00000000013d3468 ***
Aborted

查看内存泄露文件mt.log

- 0x00000000013d3468 Free 3 was never alloc'd /home/stevewong/mtrace/new.c:29

Memory not freed:
-----------------
           Address     Size     Caller
0x00000000013d3460     0x12  at 0x7f0ab50e52e8

泄露的长度是0x12=18,也就说所有的内存都没被释放。

这里有个有趣的问题,如果把数组长度设置为4的话,并没有内存泄露,而是出现了segmentation fault。求高手指教一下这是为什么。

对应的输出是

new 0x1f7a468
new 0x1f7a469
new 0x1f7a46a
new 0x1f7a46b
addr of pc: 0x1f7a468
size of pc: 8
size of class C: 1, 1
delete 0x1f7a468
Segmentation fault

对应的内存泄露文件是
No memory leaks.

8,还是把new的例子写好看看情况

#include <stdlib.h>
#include <new>
#include <mcheck.h>
#include <iostream>
using namespace std;

class C
{
public:
        C()
        {
                cout << "new " << this << endl;
        }
        ~C()
        {
                cout << "delete " << this << endl;
        }
};

int main()
{
        mtrace();
        C *pc;
        pc = new C[10];
        delete []pc;
        muntrace();
        return 0;
}

输出:

new 0x108c468
new 0x108c469
new 0x108c46a
new 0x108c46b
new 0x108c46c
new 0x108c46d
new 0x108c46e
new 0x108c46f
new 0x108c470
new 0x108c471
delete 0x108c471
delete 0x108c470
delete 0x108c46f
delete 0x108c46e
delete 0x108c46d
delete 0x108c46c
delete 0x108c46b
delete 0x108c46a
delete 0x108c469
delete 0x108c468

内存泄露查看:No memory leaks.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值