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. node.js使用express模块创建web服务器应用

    1.安装express模块 在命令行输入 npm install body-parser --save npm install express --save 2.创建app.js文件 /*应用程序入口 ...

  2. setTimeout定时器

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. layui ri laydate的常规使用,并且日期最大不能超过当前日期

    laydate的常规使用,分为两种方式实现日期组件 一.在 layui 模块中使用 下载layui   地址 :https://www.layui.com/  引入资源路径 js 和 css 通过下面 ...

  4. Maven项目构建利器01——为什么要使用Maven

    1.为什么要使用Maven a)一个项目就是一个工程 如果一个项目非常庞大,不适合用package(包)来划分模块, 最好是每一个模块对应一个工程 分工合作,借助于Maven就可以将一个项目拆分成多个 ...

  5. RHEL6查看运行级别和grub加密阻止进入单用户模式

    1.查看当前运行级别 [root@cluster01 ~]# cat /etc/redhat-release Red Hat Enterprise Linux Server release 6.5 ( ...

  6. Ansible批量部署工具

    Ansible:自动化运维工具 你需要在一台机器上yum install 一个包,这时候有一个需求,比如现在有5台机同时需要装apache这个包,那么100台呢,ssh上去就太慢了,这时候就借助到了a ...

  7. 登陆Oracle的管理员登陆

    任务栏:开始——运行,CMD 超级管理员进入系统:conn sys/oracle@prod as sysdba; 修改的代码:alter user username identified by use ...

  8. 问题:关于2.3 jmu-Java-02基本语法-03-身份证排序 (9 分)

    输出未能排序     import java.util.Scanner;     import java.util.Arrays;     public class Main {         pu ...

  9. linux如何判断上一条命令执行是否正确

    echo $? 如果输出0代表结果正确 如果输出非0代表结果错误

  10. tar命令--数据归档(一)

    虽然zip命令能够很好的将数据压缩和归档到单个文件,蛋挞不是linux 和unix的标准归档工具. ta命令最开始是用来将文件写到磁盘设备上的归档.然而他也能把输出写道文件里. 你会发现这个可选参数是 ...