恒生UFX接口引用计数心得

本文介绍在基于恒生T2SDK基础上开发对接UFX柜台时,有关引用计数的一些心得体会。
下面以配置接口和连接接口为例子来介绍,下面是文档介绍:

创建配置接口说明:

3.1.2 创建配置接口(NewConfig)
函数原型:
CConfigInterface* FUNCTION_CALL_MODE NewConfig();
输入参数:
参数名称 参数说明 用法

返回:
新的连接配置项接口。
用法说明:
通过返回的新的连接配置项接口,设置相应的连接属性,具体的接口说明参照下面的CConfigInterface接口说明。
注意
NewConfig()返回的接口,必须调用AddRef,否则调用Release接口就无法释放

创建连接接口说明:

3.1.3 创建连接接口(NewConnection)
函数原型:
CConnectionInterface* FUNCTION_CALL_MODE NewConnection(CConfigInterface *lpConfig);
输入参数:
参数名称 参数说明 用法
CConfigInterface *lpConfig 配置对象,通过NewConfig()返回 输入参数
返回:
新的连接接口,所有发包收包都是建立在连接接口之上。
用法说明:
通过返回的连接接口指针,就可以访问服务端,发功能号,收应答,所有操作都是基于连接。
注意
NewConnection ()返回的接口,必须调用AddRef,否则调用Release接口就无法释放

文档指出,在使用NewXX类返回的指针时,必须调用AddRef,在不需要使用时,调用Release来释放引用计数。看到这里,心里就有一个疑问,在调用CConnectionInterface* pConnect = NewConnection(lpConfig)时,lpConfig的引用计数会增加吗?如果此时增加,那么什么时候释放呢?

原理分析

引用计数往往和一块申请好的内存相互关联,在这块内存被申请者申请后(此处是NewConfig,引用计数为1),传递给其他模块使用(此处为NewConnection的入参)时,需要由其他模块对这块内存维护引用计数。从这个角度出发,NewConnection操作会增加传入指针的引用计数,而对应的Release操作,会减少传入指针的引用计数。

实践验证

由于T2SDK提供的dll未附带调试信息,因此,采用内存对比法来验证调用Release函数时,是否真的释放内存。为了突出重点,此处只选用NewConfigNewConooection这两个函数来验证。

  • 第一步

CConfigInterface * lpConfig = NewConfig();   // 创建配置接口
lpConfig->AddRef();
//lpConfig->AddRef();
lpConfig->Release();
//lpConfig->Release();

方法:观察 lpConfig 所指向的内存有效性来验证释放内存有效性。

结论:AddRef和Release要一对一调用才能正确释放内存,两次AddRef对应一次Release,内存不会释放,一次AddRef对应两次Release,会触发异常。

  • 第二步

CConfigInterface * lpConfig = NewConfig();   // 创建配置接口
lpConfig->AddRef();

CConnectionInterface* lpConnect = NewConnection(lpConfig);  // 创建连接接口 
lpConnect->AddRef();

// 类型1
lpConfig->Release();
lpConfig->Release();  // 调用此句,内存释放,说明 NewConnection 内部在创建成功的情况下,会对入参增加引用计数

// 类型2
lpConnect->Release();
lpConfig->Release();
lpConfig->Release();  // 调用到此处会崩溃,说明调用 lpConnect->Release() 时,会对之前的入参减少引用计数

// 类型3
lpConnect->Release();
lpConnect = NULL;
lpConfig->Release();  // 能够正常释放内存
lpConfig = NULL;	  // 防止后续代码误用

小结,NewConnection函数以及其他New类型函数,对传入的NewXXX类型入参会增加引用计数,调用Release函数时,会减少对应的引用计数。从语义上来说,调用Release表明当前模块不再关心该内存内容,以防后续业务代码误用,最好将对应指针置为空。

如果是NewXXX返回的句柄在后续业务中需要继续使用,那么将此对象保存为成员函数对象,在整个生命周期中都维持有效,直到最终退出时,再释放对应内存。

posted @ 2019-02-25 11:31  浩天之家  阅读(917)  评论(0编辑  收藏  举报