【工作总结】内存泄漏总结

    这篇博文写了放在草稿箱很久一直没整理好,现在刚好又碰到内存泄露,所以花一下午时间整理一下发表出来。

    一、内存泄漏高发地带

    1、new/delete或malloc/free不成对。

    2、从函数return的一段内存。

    char* GetMem(int size)
    {
        char *p = new char[size];
        return p;
    }

    char *p = GetMem();
    strcpy(p, "hahahaha\0");

    //此处容易忘记delete p;

 

    3、init后忘记release,这是一般在使用第三方库时候,申请了资源,在使用完忘记释放。

    4、往容器中比如vector、list、map中插入了一段内存,在使用完未进行释放。

 

    vector<char*> vec;
    char *p = new char[16];
    memset(p, 0, 16);
    vec.push_back(p);
    
    //在vec.pop以后忘记delete p

 

    5、catch,在程序执行过程中产生了异常,直接进入catch,如果处理不当,可能会产生内存泄露。

void TestCatch()
{
    try
    {
        char *p = new char[16];
        
        doSomething();
        //如果doSomething出现异常,直接进入catch,p没有被delete

        delete p;
        p = NULL;
    }
    catch (exception e)
    {

    }
}

    6、虚析构函数,在多态中,一定要将基类的析构函数设置为virtual。如果在析构函数中有内存释放的操作,且基类的析构函数没有设置为vitual的情况下,可能会发生内存泄露。

class Person
{
public:
    Person()
    {
        m_pName = new char[20];
    }
    
    virtual ~Person()
    {
        delete m_pName;
        m_pName = NULL;
    }

private:
    char *m_pName;
};

class Coder : public Person
{
public:
    Coder(){}
    ~Coder(){}

    void doCode()
    {
        cout << "code" << endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Person *p = NULL;
    p = new Coder();
    p->doCode();

    return 0;
}

//在上面的代码中,如果Person的析构函数不是virtual,p则不会调用Person的析构函数,m_pName也不会被释放。

    8、线程退出,在多线程中,线程退出时忘记释放内存也是造成内存泄露高频发生地段。

    9、拷贝构造函数。拷贝构造构造函数的返回值和传入值一定要是引用类型,否则会栈溢出。原因是当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的调用来生     成函数中的对象.这样会导致无限循环地调用拷贝构造函数,直至栈溢出

    二、如何预防内存泄露

    1、养成良好的编码习惯,new/delete或malloc/free或第三方库申请和释放资源的接口成对出现。

    2、使用内存池。

    3、使用智能指针。

    4、使用自定义内存管理类。

    三、检测内存泄露

   1、手动检测

    如果代码文件比较少,即可通过代码搜索工具全工程搜索出malloc、new关键字,然后找到相应的free或delete。

    2、Valgrind

    点击下载,最新版本是3.9.0。

    使用方法可以参考官方文档,点这里

    安装就是常规的./configure && make &&make install。

    安装完成以后就可以使用valgrind来检测程序是否存在内存问题。可以参考这篇博文

posted @ 2014-08-30 17:45  绿茵飞狼  阅读(174)  评论(0编辑  收藏  举报