CORBA Programming with TAO - 4.Basic Functions(常用基本方法解析)
摘要:
简要介绍CORBA规范定义的几个常用基本方法的功能及应用中需要注意的问题。
正文:
idl编译器会为每个在idl中声明的interface生成一个对应的代理基类:
class InterfaceName;
以及两个对象引用类型:
InterfaceName_ptr
和
InterfaceName_var
前者是一个指针类型,其定义往往是:
typedef InterfaceName* InterfaceName;
因此,不作过多讨论。
InterfaceName_var则是一个智能指针类,通过使用智能指针类,免去了我们手工维护指针引用计数的工作,大大简化了应用程序的编写。
下面重点对代理基类和_var智能指针类中的几个基本方法进行简单说明。
一、代理基类中定义的几个基本方法
每个代理基类(以及CORBA::Object)都提供如下几个静态方法:
· _duplicate
返回一个参数指针的拷贝(为了免去对象深拷贝所引起的消耗,实际是通过调整引用计数的方法实现的)
· _nil
返回相应接口类型的空引用
· _narrow
尝试将参数指针转型为目标指针,若转换失败,则返回目标类型的空引用。
除了以上静态方法,每个代理类还包括两个方法:
· _is_a
该方法接收一个类型id信息const char *type_id,并返回一个CORBA::Boolean,用于判断某个引用是否是type_id所指示的类型。
· _this
该方法返回当前对象的拷贝的引用。
· _add_ref/_remove_ref
用于增加引用计数和减小引用计数,在我们编写接口实现时可能会用到(客户程序中无法使用这两个方法,因为只有Skeleton代码中会生成这两个方法,客户程序代码也没有必要使用这两个方法来维护引用计数)。
此外,在CORBA命名空间中还定义了:
· CORBA::is_nil
判断某个ptr是否为空
· CORBA::release
释放参数对象。
而为了比较两个引用是否相同,CORBA::Object中定义了方法:
· is_equivalent
按照CORBA规范,不使用以上基本方法对CORBA对象或对象指针进行比较、类型转换、非空测试等所产生的行为都是未定义的。
这几个方法本身比较简单,并且后续的文章中将看到上述各基本方法的使用,这里就先不举例了。
二、_var智能指针类中的基本方法
按照CORBA规范,每个_var智能指针类都包括如下几个方法:
· in
· out
· inout
· _retn
· ptr
掌握这几个方法的最简单的方法是学习CORBA::String_var类的实现。CORBA::String_var是CORBA::String类的智能指针类,其中封装了一个char*指针。我们来看看TAO是如何实现这几个方法的(见%TAO_ROOT%/tao/CORBA_String.inl):
ACE_INLINE const char *
CORBA::String_var::in (void) const
{
return this->ptr_;
}
ACE_INLINE char *&
CORBA::String_var::inout (void)
{
return this->ptr_;
}
ACE_INLINE char *&
CORBA::String_var::out (void)
{
CORBA::string_free (this->ptr_);
this->ptr_ = 0;
return this->ptr_;
}
ACE_INLINE char *
CORBA::String_var::_retn (void)
{
char *temp = this->ptr_;
this->ptr_ = 0;
return temp;
}
ACE_INLINE char *
CORBA::String_var::ptr (void)
{
return this->ptr_;
}
表面看来似乎没有什么值得注意的,只是返回了几个不同类型的指针:in方法返回一个指针(因仅作为传入参数),inout方法返回一个指针的引用(因不仅要作我传入参数,还要通过函数调用修改其内容),out方法同样返回一个指针的引用(因需要通过函数调用修改其内容),inout方法返回一个指针(因仅作为返回参数,不能修改),ptr也返回一个普通指针,同样也不能修改内容。
但仔细看一看_retn的实现,你会发现,该方法首先保存了指针的内容,然后将指针清0(这样当String_var被释放时就不会free原来的地址空间),最后将该指针返回。也就是说,通过该方法调用,String_var对象所指向的地址空间的控制权被交给了调用该方法的一方,同样,释放地址空间的工作也应该由调用该方法的一方来完成。
而对于out方法,为了保证原指针被安全释放,该方法先释放原来指向的地址空间,并将指针清0,最后返回该指针的引用。因此,被调用的方法内部应负责为该对象分配空间,而释放该空间的工作则是由调用方完成的。
其他对象上述方法的实现与String_var在原理上是基本一致的,只是IDL编译器tao_idl在生成stub和skeleton代码时会分别为定长结构体和变长结构体应用不同的类模板,从而生成不同类型的_var类。对于定长结构体,应用的类模板为TAO_Fixed_Var_T,而对于变长结构体,应用的类模板为TAO_Var_Var_T。二者的区别在于对于定长结构体而言,_retn和out方法与inout方法的实现是一样的,没有清0的过程,以下是TAO_Fixed_Var_T模板类中的相关代码:
// Mapping for fixed size.
template<typename T>
ACE_INLINE
T &
TAO_Fixed_Var_T<T>::out (void)
{
return *this->ptr_;
}
template<typename T>
ACE_INLINE
T
TAO_Fixed_Var_T<T>::_retn (void)
{
return *this->ptr_;
}
关于_var类的更多信息,可参考%TAO_ROOT%/tao/VarOut_T.inl,或:
三、典型问题解析
上面简单介绍了CORBA编程中常用的几个基本方法,下面在此基础上对内存管理相关的几个问题进行简要分析。
· 包含变长成员变量的结构体的内存释放问题
以下面的idl为例:
struct DemoStruct {
string name_;
};
对于如下的代码:
int main() {
//...
DemoStruct_var demo = new DemoStruct;
demo.name_ = CORBA::string_dup("Hello");
//...
}
由于我们使用了_var智能指针类,通过new动态分配的空间会在demo对象被销毁时被释放,但是其中通过CORBA::string_dup为成员变量name_所分配的空间是否会泄漏呢?
答案是:不会。这是因为idl文件中结构体的string成员变量经过tao_idl编译后,被映射为TAO_String_Manager,这种类型与String_var基本是一样的,只是String_var不带任何参数的构造函数会将指针ptr_初始化为0,而TAO_String_Manager不带任何参数的构造函数则会将ptr_初始化成一个空字符串,具体可见%TAO_ROOT%/tao/Managed_Types.i及%TAO_ROOT%/tao/CORBA_String.inl。
因此,当结构体被释放时,我们就无需为其中的string的释放问题担心。对于其它包含变长类型的结构体而言,情况是一样的。
· _var类使用的误区
在使用String_var时有一个问题需要注意,String_var提供了三个构造函数(见%TAO_ROOT%/tao/CORBA_String.h):
CORBA::String_var::String_var (char *p)
: ptr_ (p)
{
}
ACE_INLINE
CORBA::String_var::String_var (const char *p)
: ptr_ (CORBA::string_dup (p))
{
}
CORBA::String_var::String_var (const CORBA::String_var& r)
{
this->ptr_ = CORBA::string_dup (r.ptr_);
}
第一个构造函数仅对指针p进行浅拷贝,保存到内部的ptr_中,而后面两个则通过深拷贝来构造String_var对象。
两种不同的构造方式区别虽然比较小,但可能引起一些十分隐蔽的问题。如下面的代码就存在问题:
String_var str("Hello");
因为上述代码会使用第一个而不是第二个构造函数来构造str,从而使得str获得静态地址空间"Hello"的控制权,并在str被析构时尝试释放该空间,这显然是错误的。要避免该错误,我们应该总是强制使用第二个构造函数,或在构造Stirng_var对象前主动复制String的内容,如:
String_var str1((const char*)"Hello");
String_var str2(CORBA::string_dup("Hello"));
除非你清楚地知道第一个构造函数是你需要的。
对于其它_var类型而言,不存在与上面第二种构造方式等价的构造函数,我们总是使用第一种形式的构造函数,即新构造的_var对象会获得指针的控制权。
与上面第三种构造方式类似,如果你传入的是一个_var引用,则使用的是如下的构造函数:
template<typename T>
TAO_Var_Base_T<T>::TAO_Var_Base_T (const TAO_Var_Base_T<T> & p)
: ptr_ (p.ptr_ ? new T (*p.ptr_) : 0)
{
}
该构造函数会对传入的_var引用进行深拷贝。
· 对远程方法调用内存管理问题的解释
CORBA内存分配/释放的原则很简单:各自负责自己分配空间的释放,C/S两端内存的分配与释放(以及更新)不会自动通知另一方。
对于Client代码而言,由Client代码负责释放的空间还包括ORB在unmarshalling期间创建的Server的指针的镜像,即Server端指针的本地拷贝,这些空间可能是out/inout参数或者作为接口方法的返回值通过方法调用获得的。
这在理解上应该没有什么问题。但是,其中对于Server方的内存管理,我们没有考虑。以如下代码为例:
DemoStruct* DemoIntf::foo() {
DemoStruct_var var = new DemoStruct;
//...
return var._retn();
}
当函数返回时,Client方ORB会通过unmarshalling创建一个该指针所指内存区域的镜像,然后访问该指针,最后由Client方负责该区域的释放;但是我们说过,C/S双方分配和释放内存并不会自动通知另一方,对于Server方而言,由于_retn方法会释放原_var对象对其ptr_指针所指地址空间的控制权,原来由_var对象所管理的空间似乎变得失去了控制,那么这一部分内存是否会泄漏呢?
同样,答案是不会,这是因为ORB在将该指针进行marshalling并传递给Client后,会负责指针所指空间的释放,同样对于in、out、inout参数的管理也是类似的。
结合上面对Server方内存管理方式的讨论,我们来看看下面的例子。
对于如下的idl文件:
struct DemoStruct {
string name_;
};
interface DemoIntf {
DemoStruct get();
};
有类似下面的实现:
class DemoIntf : ...
{
private:
DemoStruct_var demo_;
public:
DemoStruct* get() {
return demo_;
}
};
上述实现初看起来可以正常工作,但是根据上面的讨论,ORB会释放返回值指针的地址空间,这将导致demo_被意外释放,最终导致错误的发生。因此,我们应该将实现代码改为:
DemoStruct* get() {
::Device::DeviceID_var dev_id = new ::Device::DeviceID;
dev_id->device_name = CORBA::string_dup(id_->device_name);
return dev_id._retn();
}
而客户方代码的代码是这样的:
::Device::DeviceID_var device_id = this->device_id();
参考:
1. Michi Henning, Steve Vinoski. Advanced CORBA Programming with C++. Addison-Wesley, 1999.
相关推荐
CORBA Programming with TAO,整理自“大卫的思维空间”,内容简洁,快速入门。格式制作为CHM,方便阅读。
《CORBA Programming with TAO》是一篇专门为CORBA编程初学者准备的文章,它详细介绍了如何使用TAO(The ACE ORB)这一实现CORBA标准的开源ORB(对象请求代理)。TAO是ACE(Adaptive Communication Environment)...
8. **JEP 320: Remove the Java EE and CORBA Modules**:移除了不再维护的Java EE和CORBA模块,使JDK更加精简。 9. **其他改进**:还包括性能优化、错误修复、新的API添加等。 Red Hat是一个知名的Linux发行版和...
《Glassfish-CORBA-Source-3.1.0-b021与Fedora数据传输对象解析》 Glassfish-CORBA-Source-3.1.0-b021.zip是一个压缩包,其中包含了Glassfish服务器的一个特定版本的CORBA(Common Object Request Broker ...
8. **JEP 320:移除Java EE和Corba模块**:为了简化JDK,不再包含Java EE和Corba相关的模块,但这并不意味着Java不再支持企业级开发,而是鼓励使用更现代的微服务架构。 9. **JEP 321:HTTP/2和TLS的HTTP/2客户端**...
./configure --prefix=/path/to/install --with-tao --with-log-support ``` 2. 编译: 使用`make`命令开始编译过程,这可能会花费一些时间: ```bash make -j 4 ``` `-j 4`参数表示使用4个线程并行编译,...
axis2-corba-1.5.4.jar axis2-fastinfoset-1.5.4.jar axis2-java2wsdl-1.5.4.jar axis2-jaxbri-1.5.4.jar axis2-jaxws-1.5.4.jar axis2-jibx-1.5.4.jar axis2-json-1.5.4.jar axis2-kernel-1.5.4.jar axis2-metadata...
axis2-corba-1.7.4.jar axis2-fastinfoset-1.7.4.jar axis2-java2wsdl-1.7.4.jar axis2-jaxbri-1.7.4.jar axis2-jaxws-1.7.4.jar axis2-jibx-1.7.4.jar axis2-json-1.7.4.jar axis2-kernel-1.7.4.jar axis2-metadata...
4. **文本块(JEP 329)**: 这一特性使得在代码中表示多行字符串变得更加简单,减少了转义字符的使用,提高了代码的可读性。 5. **改进的JNI签名(JEP 330)**: JDK 11改进了JNI头文件的生成,允许在签名中使用`?`...
4. **字符串切片**:新增`String#lines()`方法,方便处理文本流,并引入`String#strip()`和`String#stripIndent()`来简化字符串的处理。 5. **ZGC:Zero Garbage Collector**:一种低延迟的垃圾收集器,适用于大...
axis2-corba-1.5.4.jar axis2-fastinfoset-1.5.4.jar axis2-java2wsdl-1.5.4.jar axis2-jaxbri-1.5.4.jar axis2-jaxws-1.5.4.jar axis2-jibx-1.5.4.jar axis2-json-1.5.4.jar axis2-kernel-1.5.4.jar axis2-metadata...
《深入解析JDK 11.0.16.1 Linux x64版本》 在IT领域,Java开发工具包(Java Development Kit,简称JDK)是Java编程的基础,它包含了一组用于开发和运行Java应用程序的工具。本文将详细讨论JDK 11.0.16.1的Linux x64...
4. **命名与目录服务**:提供CORBA标准的NFS服务,使得对象可以根据名称进行查找和管理,增强了系统的可扩展性和可管理性。 5. **事件服务**:支持CORBA的Event Service,使得对象可以订阅和发布事件,增强了系统的...
在“CORBA-sample-of-java.rar_corba”这个压缩包中,包含了一个基于Java实现的CORBA实例,以及一个名为“基于Java的CORBA实验参考.mht”的文档,用于指导如何编译和运行这个程序。 **CORBA的核心概念** 1. **ORB...
1. **Ant的基本概念** - **构建工具**:Ant是一个基于Java的构建工具,与Make类似,但设计更为灵活,适合Java项目。 - **XML配置**:Ant通过XML文件定义构建过程,其中包含了一系列的任务(tasks)和目标(targets...
《Advanced CORBA Programming with C++》是一本专为高级CORBA编程者设计的书籍,由Addison-Wesley出版社出版。这本书深入探讨了CORBA(Common Object Request Broker Architecture,公共对象请求代理架构)的高级...
Advanced CORBA® Programming with C++ provides designers and developers with the tools required to understand CORBA technology at the architectural, design, and source code levels. This book offers ...
官方版本,亲测可用
- 移除了Java EE和Corba模块,简化了平台。 - 引入了HTTP客户端API(java.net.http),方便开发人员进行网络通信。 - 新增了动态类型语言支持,如lambda表达式和方法引用来提高代码的简洁性。 - 改进了字符串...
《Advanced CORBA Programming with C++》是由Addison-Wesley出版社出版的一本深入探讨CORBA(Common Object Request Broker Architecture)编程技术的专业书籍。这本书专为经验丰富的C++开发者设计,旨在帮助他们...