zoukankan      html  css  js  c++  java
  • 解决项目中内存泄漏的问题

    根据大佬的文章而来,加上了自己代码的具体例子

    关于内存泄漏的问题,根据经验总结如下(持续补充):

    原则是,**有 ** new 就有delete

    # 普通C++

    1 Static对象

    尤其是单例模式,目的是整个程序的生命周期只有一个对象实例,但在退出时必须记得删除。(比如绑定mainwindow的析构函数,或者closeEvent等)。

    /**
     * @brief The MAP_GR_DIS class
     * 采用单例模式,在private区有单一实例
     * 获取实例的方法:
     *  MAP_GR_DIS::getInstance
     * 举个例子:
     * 比如我想调用NoMeasuringDistance()这个函数
     * 就可以MAP_GR_DIS::getInstance()->NoMeasuringDistance();
     */
    
    class MAP_GR_DIS: public MAP_OSG_BaseHandler
    {
    
    
    public:
         MAP_GR_DIS();
        static MAP_GR_DIS * getInstance();      //获取单一实例的办法
        static bool clickState;
        static void deleteDistanceObject();
    private:
        static MAP_GR_DIS * disObject;
    

    比如说这个类,MAP_GR_DIS,它是单一实例的,所以在退出时,应该清空这个类的m_instance;

    那么实现的最后方法是

    声明:

    static void deleteDistanceObject();
    

    定义:

    void MAP_GR_DIS::deleteDistanceObject()
    {
        if(disObject)
            delete disObject;
        disObject=nullptr;
    }
    

    2 类成员指针

    所有类都提供析构函数,检查类内有无指针成员,需不需要负责其销毁。注意,并不是有指针就要delete,比如类内保存的观察指针,属于观察者模式,其销毁责任不在该类中。要特别注意析构函数的删除和调用,析构时很可能整个程序都退出了,很多类外的变量实际上已经访问不到了,即已先于该类被析构。此时要是调用即属于野指针,导致崩溃(见文档《堆内存出现野指针记录》)。同时不属于该类销毁的指针被销毁了会导致重复delete,同样导致崩溃。

    # osg相关

    3 osg对象树

    osg对象树是建立在osg::Referenced基类上的,即引用计数,库内绝大部分指针都使用osg::ref_ptr或osg::observer_ptr,在引用计数为0时会自动释放内存,属于有new就要delete的特例(其实只是库帮你做了)。

    所以在根据osg项目中的文档,建议osg相关所有指针使用osg::ref_ptr(有特例,后面提到)。这时,基本不需要你去维护内存了。比如一个类成员为osg::ref_ptr,那在该类析构时,osg::ref_ptr对象(指保持指针的类)析构,就会自动delete掉指针对应的内存。需要做的只是m_mypointer = nullptr。

    另外,父控件销毁时,会自动销毁子控件,所以只要控制根节点即可。一般情况下,即osgView::View,项目中即removeView(MAP_OSG_BaseView)的接口,删除根节点。

    特例情况是,观察者指针,即指针的所有权不在你身上,你只有观察、调用、修饰等职责,尽量不要使用osg::ref_ptr了,而是改用osg:: observer_ptr,该指针的作用是:

    Smart pointer for observed objects, that automatically set pointers to them to null when they are deleted.

    或者干脆直接用普通的指针也可。如使用到osg::ref_ptr,即使你没用销毁责任,也必须在析构时调用m_mypointer = nullptr。

    4 Qt对象树

    跟osg类似,同样是具有对象树的结构,父亲会负责孩子的销毁。但,特别强调一点,并不是说使用了Qt的类就不用负责内存管理了,其判断标准为,当且仅当一个对象满足如下条件:
    1.该对象是QObject的派生类
    2.该对象的父类不为NULL
    那么,该对象的父类删除时,该对象会被自动删除,无需手动释放。

    可能出现的错误就在于父类,习惯性传入nullptr作为父指针的情况下,即顶级控件,就要负责其内存管理,当然很多情况下Qt窗口之类的,退出即删除,自动delete ui,但要考虑一点,如果该窗口打开的情况下,程序就退出了,涉及模态之类的设置。总之,推荐传入父指针初始化控件。

    一个最常见的例子就是,最顶级的界面,即mainwindow,该类在main中初始化,肯定没有父亲,所以必须自己负责其销毁。可以看到绝大部分Qt官方实例的写法是,Mainwindow w; w.show(); 而不是Mainwindow *w = new Mainwindow; w->show(); 即堆内存和栈内存的区别。

  • 相关阅读:
    HDU 1850 Being a Good Boy in Spring Festival
    UESTC 1080 空心矩阵
    HDU 2491 Priest John's Busiest Day
    UVALive 6181
    ZOJ 2674 Strange Limit
    UVA 12532 Interval Product
    UESTC 1237 质因子分解
    UESTC 1014 Shot
    xe5 android listbox的 TMetropolisUIListBoxItem
    xe5 android tts(Text To Speech)
  • 原文地址:https://www.cnblogs.com/yahoo17/p/12488631.html
Copyright © 2011-2022 走看看