使用ACE_Message_Block需要注意的问题

来源:互联网 发布:程序员生日快乐代码 编辑:程序博客网 时间:2024/04/29 17:16

ACE_Message_Block使用注意

作者: ydogg 如需转载,请注明.

作为ACE_Message_Block功能和实现浅析一文的补充.

1.     Message_Flags类型的成员变量flags_

ACE_Message_Block和内部的ACE_Data_Block都拥有Message_Flags类型的成员flags_,用于指示它们是否可以释放它们所持有的空间.对于ACE_Message_Block来说,它持有的空间意为ACE_Data_Block本身. 对于ACE_Data_Block来说,它持有的空间意为它管理的数据空间.flag_中设置了ACE_Message_Block::DONT_DELETE标志位,意思为ACE_Message_BlockACE_Data_Block不要进行释放,反之是需要释放.

ACE_Message_Block的构造和初始化函数中的flag参数实际上是提供给ACE_Data_Block初始化时使用的.如果为ACE_Message_Block提供的构造参数msg_data不为NULL,默认的flags就为ACE_Message_Block::DONT_DELETE,而且将作为ACE_Data_Block的构造参数使用,不会用于自身的flags_初始化.惟一的例外是显式的用ACE_Data_Block*初始化ACE_Message_Block,这时传递的flags会用于初始化ACE_Message_Block本身的flags_.

惟一例外的构造函数:

ACE_Message_Block::ACE_Message_Block (
ACE_Data_Block 
*data_block,
ACE_Message_Block::Message_Flags flags,  
ACE_Allocator 
*message_block_allocator)

注意区分: 

ACE_Message_Block::flags()
ACE_Message_Block
::set_flags()
ACE_Message_Block
::clr_flags()
ACE_Message_Block
::self_flags()
ACE_Message_Block
::set_self_flags()
ACE_Message_Block
::clr_self_flags()

2.     提供给ACE_Message_Block初始化的空间地址

可以看出,当提供给一个非NULL地址用于ACE_Message_Block实例构造时,实例实际上并不会再主动申请新的空间,而是直接利用提供的空间.所以当你用一个临时的缓冲来构造一个ACE_Message_Block实例,需要特别注意,在这个实例的生存期内都要保证这个临时缓冲的有效性.否则ACE_Message_Block可能持有的就是一个悬空指针,后果严重.另一个方面,如果用一个Heap上申请的空间来构造一个ACE_Message_Block实例,因为此时默认不设置ACE_Message_Block::DONT_DELETE标志位,当实例析构时,不会帮助你释放空间,会造成内存泄漏的危险.解决的方法要么是自己来管理这个空间,要么是清除ACE_Message_Block::DONT_DELETE标志位,ACE_Message_Block去自己去负责管理.

也就是,参数不为空,当消息块被销毁时它就不会删除数据缓冲区。这是一个重要特性,必须牢牢记住.

3.     size()函数的风险

这还是一个内存的处理问题. ACE_Message_Block有一个size(int len)函数,可以用它动态的决定ACE_Message_Block内的可用空间.len大于当前ACE_Message_Block的最大容量时, ACE_Message_Block将会申请新的空间,而放弃原来给它的那块空间. 如果没有设置ACE_Message_Block::DONT_DELETE标志位,ACE_Message_Block不会帮助你释放原有空间. 这时就要注意释放原有的空间,防止出现内存泄漏.

4.     需要小心的release()函数

首先,release()只适合生成在heap上的对象调用,因为release()会试图释放本身(delete this).其次,如果ACE_Message_Block是个复合消息,那么release()将会把它们通通释放.所以如果只是想释放这个对象本身,需要显式的调用delete.

如果一个复合消息是在栈上复合而成的,基于前面所说的问题,不能使用release()函数,那只有手工的对所有的单向链消息进行释放了. 

5.     copy()函数

copy(const char *buf, size_t n)函数用起来方便,因为它会帮你自动设置写指针,
免去了忘记设置wr_ptr(n)时的苦恼.
但使用它的兄弟copy(const char *buf)可要注意,因为它会帮你把字符串末尾的0也复制,长度也会多1.这个特性可能会在你拼接二进制协议时带来一些古怪的问题.