• SOUI中对象的生命周期管理


    C++程序员最难的一环就是处理内存泄漏。

    很多情况下,一个对象在一个模块里分配了内存,忘记了释放,或者在另一个模块里释放都会导致内存相关的问题。

    SOUI中大部分暴露在应用层的对象都使用类似COM的引用计数来管理对象的生命周期,包含SWindow, ISkin, EventArg, SStringT, IRenderTarget, IBitmap, IAdapter以及各种扩展组件。

    SOUI中引用计数的基类是:SOUI::IObfRef

    namespace SOUI
    {
        struct IObjRef
        {
            virtual long AddRef() PURE;
    
            virtual long Release() PURE;
        
            virtual void OnFinalRelease() PURE;
        };
    }

    SOUI中使用引用计数有一个简单的原则:一个对象,谁AddRef,那也应该它来Release。

    经常有人问:为什么我调用了SImageWnd::SetImage就有内存泄漏了?

    用户的代码可能是下面这样的:

        bool SDemoSkin::SetImage(SStringW imgfile)
        {
            m_bIsColor = false;
            m_FilePath = imgfile;
            IBitmap *image = LOADIMAGE2(L"file:" + imgfile);
            if (image)
            {
                SetImage(image);
                //image->Release();
                return true;
            }
            return false;
        }

    这个问题很简单,看一下SetImage(IBitmap*)这个方法的代码就知道,它会自己持有这个IBitmap*对象。

    通常这是用户从文件或者内存加载后创建的IBitmap对象,所有SOUI对象的创建都自动调用了AddRef,因此调用它个方法的人调用完成后,不再使用这个对象,则应该相应的调用一下Release(即打开代码中被注释的行)。

    SOUI中也提供了一个智能指针来简化这个引用计数的操作:SAutoRefPtr (2.x是CAutoRefPtr)

    使用智能指针,上面代码可以改写为:

     bool SDemoSkin::SetImage(SStringW imgfile)
        {
            m_bIsColor = false;
            m_FilePath = imgfile;
            SAutoRefPtr<IBitmap> image;
            image.Attach(LOADIMAGE2(L"file:" + imgfile));
            if (image)
            {
                SetImage(image);
                return true;
            }
            return false;
        }

    注:由于LOADIMAGE2内部已经调用了AddRef,而智能指针直接赋值时会自动AddRef,因此这里要用image.Attach来获得指针。Attach不会自动调用AddRef.

    使用好IObjRef,配合上SAutoRefPtr,可以将SOUI的内存泄漏问题降低很多。

    启程软件 2019年10月17日

  • 相关阅读:
    安装django(使用国内镜像)
    adb工具安装与配置
    mysql
    Charles抓包(iOS的http/https请求)
    selenium+python第一个自动化脚本
    selenium+python环境搭建
    python,你好!
    tjkd-html
    asp
    uglifyjs压缩批处理
  • 原文地址:https://www.cnblogs.com/setoutsoft/p/11693747.html
Copyright © 2020-2023  润新知