SOUI官方论坛

 找回密码
 立即注册
查看: 1674|回复: 3

SOUI中对象的生命周期管理

[复制链接]
  • TA的每日心情
    开心
    6 天前
  • 签到天数: 942 天

    [LV.10]以坛为家III

    580

    主题

    1340

    帖子

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    28797
    发表于 2019-10-18 08:39:08 | 显示全部楼层 |阅读模式
    C++程序员最难的一环就是处理内存泄漏。
    很多情况下,一个对象在一个模块里分配了内存,忘记了释放,或者在另一个模块里释放都会导致内存相关的问题。
    SOUI中大部分暴露在应用层的对象都使用类似COM的引用计数来管理对象的生命周期,包含SWindow, ISkin, EventArg, SStringT, IRenderTarget, IBitmap, IAdapter以及各种扩展组件。
    SOUI中引用计数的基类是:SOUI::IObfRef
    1. namespace SOUI
    2. {
    3.     struct IObjRef
    4.     {
    5.         virtual long AddRef() PURE;

    6.         virtual long Release() PURE;
    7.    
    8.         virtual void OnFinalRelease() PURE;
    9.     };
    10. }
    复制代码
    SOUI中使用引用计数有一个简单的原则:一个对象,谁AddRef,那也应该它来Release。
    经常有人问:为什么我调用了SImageWnd::SetImage就有内存泄漏了?
    用户的代码可能是下面这样的:
    1. bool SDemoSkin::SetImage(SStringW imgfile)
    2.     {
    3.         m_bIsColor = false;
    4.         m_FilePath = imgfile;
    5.         IBitmap *image = LOADIMAGE2(L"file:" + imgfile);
    6.         if (image)
    7.         {
    8.             SetImage(image);
    9.             //image->Release();
    10.             return true;
    11.         }
    12.         return false;
    13.     }
    复制代码
    这个问题很简单,看一下SetImage(IBitmap*)这个方法的代码就知道,它会自己持有这个IBitmap*对象。
    通常这是用户从文件或者内存加载后创建的IBitmap对象,所有SOUI对象的创建都自动调用了AddRef,因此调用它个方法的人调用完成后,不再使用这个对象,则应该相应的调用一下Release(即打开代码中被注释的行)。
    SOUI中也提供了一个智能指针来简化这个引用计数的操作:SAutoRefPtr (2.x是CAutoRefPtr)
    使用智能指针,上面代码可以改写为:
    1. bool SDemoSkin::SetImage(SStringW imgfile)
    2.     {
    3.         m_bIsColor = false;
    4.         m_FilePath = imgfile;
    5.         SAutoRefPtr<IBitmap> image;
    6.         image.Attach(LOADIMAGE2(L"file:" + imgfile));
    7.         if (image)
    8.         {
    9.             SetImage(image);
    10.             return true;
    11.         }
    12.         return false;
    13.     }
    复制代码
    注:由于LOADIMAGE2内部已经调用了AddRef,而智能指针直接赋值时会自动AddRef,因此这里要用image.Attach来获得指针。Attach不会自动调用AddRef.

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

    启程软件 2019年10月17日

    该用户从未签到

    4

    主题

    67

    帖子

    1388

    积分

    06:00合体期

    Rank: 6Rank: 6

    积分
    1388
    发表于 2019-10-21 09:38:53 | 显示全部楼层
    前排支持
    回复

    使用道具 举报

  • TA的每日心情
    开心
    6 天前
  • 签到天数: 942 天

    [LV.10]以坛为家III

    580

    主题

    1340

    帖子

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    28797
     楼主| 发表于 2019-10-21 11:49:36 | 显示全部楼层

    谢谢支持

    该用户从未签到

    1

    主题

    35

    帖子

    43

    积分

    22:00筑基期

    Rank: 1

    积分
    43
    发表于 2020-4-16 18:40:13 | 显示全部楼层
    谢谢分享,看看
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|SOUI官方论坛

    GMT+8, 2024-5-4 20:28

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表