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日

SOUI中对象的生命周期管理的更多相关文章

  1. java之hibernate之session中对象的生命周期

    1. session是用来执行对象的crud操作,并且session是对象事务工厂.session是线程级别的,所以生命周期比较短. 2.session中对象的生命周期图: 3.session中对象的 ...

  2. Tomcat中组件的生命周期管理公共接口Lifecycle

    Tomcat的组件都会实现一个Lifecycle接口,以方便组件的生命周期的统一管理 interface Lifecycle 组件生命周期中主要的几个方法 增加监听器,事件委托机制 public vo ...

  3. 第四章 Spring.Net 如何管理您的类___对象的生命周期链

    各位,实在不好意思,因为有事,博客几天没更新了.前面有童鞋提到,配置 Objects.xml 路径的相关问题,这些东西是 IResource 接口的一些内容.在下一章会详细介绍. 传统的Net应用中, ...

  4. 依赖注入及AOP简述(十一)——生命周期管理 .

    2.     生命周期管理 各种依赖注入框架提供了替开发者管理各种Scope的便利功能,随之而来的就必然是被管理的依赖对象的生命周期管理的问题.所谓生命周期管理,就是一个对象在它所属的Scope中从被 ...

  5. ElasticSearch——索引生命周期管理

    从ES6.6开始,Elasticsearch提供索引生命周期管理功能,索引生命周期管理可以通过API或者kibana界面配置,详情参考[index-lifecycle-management] 本文仅通 ...

  6. Elasticsearch索引生命周期管理探索

    文章转载自: https://mp.weixin.qq.com/s?__biz=MzI2NDY1MTA3OQ==&mid=2247484130&idx=1&sn=454f199 ...

  7. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  8. [原创]java WEB学习笔记94:Hibernate学习之路---session 的管理,Session 对象的生命周期与本地线程绑定

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  9. Delphi 接口使用中,对象生命周期管理,如何释放需要注意的问题

    网上有篇文章<Delphi接口编程的两大陷阱>,里面提到接口的生存期管理的问题.但该文章里面提到的两个问题,其实都是对 Delphi 不理解导致的.   先说该篇文章中提到的第一个问题为什 ...

随机推荐

  1. luogu P2093 [国家集训队]JZPFAR

    传送门 要维护平面上点的信息,所以可以用KD-tree来维护,然后维护一个大小为\(k\)的堆,每次从根开始遍历,遇到一个点就看能不能作为前\(k\)远的点,也就是看能不能把堆中最近的点给替换掉.如果 ...

  2. linux下mysql的常用命令

    更改mysql数据库root的密码 首次进入数据库是不用密码的: [root@localhost ~]# /usr/local/mysql/bin/mysql -uroot Welcome to th ...

  3. markdown的日常使用

    # POI前端接口 ``` 描述: 项目poi接口 作者: X-Wolf 时间: -- ``` ------ [TOC] ------ ##声明 ### 请求地址 ``` DOMAIN/strateg ...

  4. 使用git配置ssh的文章推荐

    https://blog.51cto.com/sgk2011/1925922 https://www.cnblogs.com/superGG1990/p/6844952.html https://bl ...

  5. chrome插件2

    转自:http://www.codeceo.com/article/15-chrome-extension.html 1. Web Developer 支持Chrome的Web Developer扩展 ...

  6. hadoop的权限控制

    HDFS支持权限控制,但支持较弱.HDFS的设计是基于POSIX模型的,支持按用户.用户组.其他用户的读写执行控制权限.在linux命令行下,可以使用下面的命令修改文件的权限.文件所有者,文件所属组: ...

  7. laravel-admin利用ModelTree实现对分类信息的管理

    根据laravel的基本操作步骤依次完成如下操作:主要是参考laravel-admin内置的Menu菜单管理的功能,利用ModelTree实现业务中的Tree数据管理. 1. 创建模型 php art ...

  8. java知识

    DiskFileUploadhttps://blog.csdn.net/FightingITPanda/article/details/79742631 import java.util.ArrayL ...

  9. error: ‘ostream_iterator’ was not declared in this scope

    在代码中添加      #include <iterator>

  10. VMware主机使用无线上网

    VMware主机使用无线上网,默认的NAT连接在ubuntu下上不了网,需要把网络适配器改成桥接模式.