28、使用valgrind 进行vector的内存检查

基本思想:最近做项目,遇到了在android上使用c++开发时,内存泄漏和内存释放失败的情况,顾复习一下之前的知识点,顺手也记录一下;

提供一个demo和简单的分析叙述;

#include<iostream>
#include<vector>
using namespace std;
typedef struct
{
        int x;
        int y;
} Point;


class Axis
{
        public:
                Axis()
                {}
                ~Axis()
                {
                        avpoint.clear();
                        vector<Point>().swap(avpoint);
                        cout << "after swap size:" << avpoint.size() << endl;
                        cout << "after swap capacity:" << avpoint.capacity() << endl;
                        for(int i=0;i<avpppoint.size();i++)
                        {
                                if(NULL!=avpppoint[i]){
                                        delete avpppoint[i];
                                         avpppoint[i]=NULL;
                                }
                        }
                        avpppoint.clear();
                        vector<Point*>().swap(avpppoint);

                        cout << "after swap size:" << avpppoint.size() << endl;
                        cout << "after swap capacity:" << avpppoint.capacity() << endl;

                }
        private:
                int x;
                int y;
                vector<Point> avpoint;
                vector<Point*> avpppoint;
        public:
                void setx(int x)
                {this->x=x;
                }
                void sety(int y)
                {this->y=y;
                }
                void init()
                {
                        Point pp;
                        pp.x=99;
                        pp.y=999;
                        avpoint.push_back(pp);
                        Point *vppoint=new Point();
                        vppoint->x=33;
                        vppoint->y=43;
                        avpppoint.push_back(vppoint);
                }
};

int main()
{
        vector<int> v;
        for(int i=0;i<72;i++)
        {
                v.push_back(i);
        }

        cout << "size:" << v.size() << endl;
        cout << "capacity:" << v.capacity() << endl;
        v.clear();
        vector<int>().swap(v);
        cout << "after swap size:" << v.size() << endl;
        cout << "after swap capacity:" << v.capacity() << endl;
        //
        vector<Point> vp;
        Point point;
        for(int i=0;i<4;i++)
        {
                point.x=i;
                point.y=i;
                vp.push_back(point);
        }


        vp.clear();
        vector<Point>().swap(vp);
        cout << "size:" << vp.size() << endl;

        cout << "capacity:" << vp.capacity() << endl;
        
        vector<Axis*> vaxis;
        Axis *axis=new Axis();
        axis->setx(1);
        axis->sety(2);
        vaxis.push_back(axis);
        vaxis.clear();
        vector<Axis*>().swap(vaxis);
        delete axis;
        cout << "size:" << vaxis.size() << endl;
        cout << "capacity:" << vaxis.capacity() << endl;

        
        Axis *bxis=new Axis();
        bxis->init();
        delete bxis;




        return 0;
}

执行结果

ubuntu@ubuntu:~/test$ ./a.out
size:72
capacity:128
after swap size:0
after swap capacity:0
size:0
capacity:0
after swap size:0
after swap capacity:0
after swap size:0
after swap capacity:0
size:0
capacity:0
after swap size:0
after swap capacity:0
after swap size:0
after swap capacity:0

内存检查valgrind  (简单说明 我是用的gcc-5.4 valgrind 3-13 ; 编译器版本和内存检查工具不同 生成的valgrind的报告存在差异,差异在于是否输出内存池的的log信息,关于内存池的相关知识,请参考相关文档)

ubuntu@ubuntu:~/test$ G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=20 --show-reachable=yes --log-file=a.log  ./a.out
size:72
capacity:128
after swap size:0
after swap capacity:0
size:0
capacity:0
after swap size:0
after swap capacity:0
after swap size:0
after swap capacity:0
size:0
capacity:0
after swap size:0
after swap capacity:0
after swap size:0
after swap capacity:0

内存检查的log

ubuntu@ubuntu:~/test$ cat a.log
==41010== Memcheck, a memory error detector
==41010== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==41010== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==41010== Command: ./a.out
==41010== Parent PID: 22172
==41010==
==41010==
==41010== HEAP SUMMARY:
==41010==     in use at exit: 72,704 bytes in 1 blocks
==41010==   total heap usage: 19 allocs, 18 frees, 74,948 bytes allocated
==41010==
==41010== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==41010==    at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)
==41010==    by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==41010==    by 0x40106C9: call_init.part.0 (dl-init.c:72)
==41010==    by 0x40107DA: call_init (dl-init.c:30)
==41010==    by 0x40107DA: _dl_init (dl-init.c:120)
==41010==    by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
==41010==
==41010== LEAK SUMMARY:
==41010==    definitely lost: 0 bytes in 0 blocks
==41010==    indirectly lost: 0 bytes in 0 blocks
==41010==      possibly lost: 0 bytes in 0 blocks
==41010==    still reachable: 72,704 bytes in 1 blocks
==41010==         suppressed: 0 bytes in 0 blocks
==41010==
==41010== For counts of detected and suppressed errors, rerun with: -v
==41010== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

其中这段信息的含义:

==41010== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1
==41010==    at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)
==41010==    by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==41010==    by 0x40106C9: call_init.part.0 (dl-init.c:72)
==41010==    by 0x40107DA: call_init (dl-init.c:30)
==41010==    by 0x40107DA: _dl_init (dl-init.c:120)
==41010==    by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)

摘录他人的叙述:

“使用 Valgrind 分析 C++ 程序时,有一些问题需要留意。例如,这个程序并没有发生内存泄漏,但是从HEAP SUMMARY可以看到,程序分配了 2 次内存,但却只释放了 1 次内存,为什么会这样呢?

实际上这是由于 C++ 在分配内存时,为了提高效率,使用了它自己的内存池。当程序终止时,内存池的内存才会被操作系统回收,所以 Valgrind 会将这部分内存报告为 reachable 的,需要注意,reachable 的内存不代表内存泄漏,例如,从上面的输出中可以看到,有 72704 个字节是 reachable 的,但没有报告内存泄漏。”

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页