zoukankan      html  css  js  c++  java
  • 【工作总结】内存泄漏总结

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

        一、内存泄漏高发地带

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

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

        char* GetMem(int size)
        {
            char *p = new char[size];
            return p;
        }
    
        char *p = GetMem();
        strcpy(p, "hahahaha");
    
        //此处容易忘记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来检测程序是否存在内存问题。可以参考这篇博文

  • 相关阅读:
    c# 坑人的发邮件组件
    生成拼音
    FileDb
    WMI tester
    c# 纯代码调用 webservice
    c# 中 利用 CookieContainer 对 Cookie 进行序列化和反序列化校验
    在经过身份验证的服务中不支持跨域 javascript 回调
    c# 使用 namedpipe 通信
    c++ 创建线程以及参数传递
    c#函数地址传入c++
  • 原文地址:https://www.cnblogs.com/zhiqli/p/3504296.html
Copyright © 2011-2022 走看看