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(); 即堆内存和栈内存的区别。

  • 相关阅读:
    【C#图解教程学习笔记】第13章 委托
    TreeView树,全选,反选,平级选操作
    C# 字符串和字节数组转换
    WebServices 使用Session
    Win8.1下Flash Builder 提示: 找不到所需的Adobe Flash Player调试器版本,解决办法
    C# winform DataGridView 绑定数据的的几种方法
    .NET Core GB2312
    [WPF 学习] 7.2 模板打印
    [WPF 学习] 7.1 多页打印
    [WPF 学习] 7 打印相关的东东
  • 原文地址:https://www.cnblogs.com/yahoo17/p/12488631.html
Copyright © 2011-2022 走看看