peakzhang 发表于 2007-12-21 21:54:36

ACE_Data_Block的内存泄漏,请大家指教!

看了ACE5.5的ACE_Message_Block和ACE_Data_Block代码,觉得有内存泄漏问题。
对下面的ACE_Message_Block构函,如果data为0(null),ACE_Message_Block
的flags_标志为0(故ACE_Data_Block的引用计数为0时将调用ACE_Data_Block的析构函数);
ACE_Data_Block标志为ACE_Message_Block::DONT_DELETE;
在ACE_Data_Block的构函中会调用ACE_ALLOCATOR (this->base_,
                   (char *) this->allocator_strategy_->malloc (size)); 为base_分配内存
                  
但在ACE_Data_Block的析构函数中,由于ACE_Data_Block标志为ACE_Message_Block::DONT_DELETE,
故不会释放base_的内存!
                  
   相关代码如下:               

ACE_Message_Block::ACE_Message_Block (const char *data,
                                    size_t size,
                                    unsigned long priority)
: flags_ (0),
    data_block_ (0)
{
ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");

if (this->init_i (size,    // size
                  MB_DATA, // type
                  0,       // cont
                  data,    // data=null
                  0,       // allocator
                  0,       // locking strategy
                  ACE_Message_Block::DONT_DELETE, // flags   
                  priority, // priority
                  ACE_Time_Value::zero,   // execution time
                  ACE_Time_Value::max_time, // absolute time of deadline
                  0,// data block
                  0,// data_block allocator
                  0) == -1) // message_block allocator
    ACE_ERROR ((LM_ERROR,
                ACE_LIB_TEXT ("ACE_Message_Block")));
}


ACE_Message_Block::init_i (size_t size,
                           ACE_Message_Type msg_type,
                           ACE_Message_Block *msg_cont,
                           const char *msg_data,
                           ACE_Allocator *allocator_strategy,
                           ACE_Lock *locking_strategy,
                           Message_Flags flags,
                           unsigned long priority,
                           const ACE_Time_Value &execution_time,
                           const ACE_Time_Value &deadline_time,
                           ACE_Data_Block *db,
                           ACE_Allocator *data_block_allocator,
                           ACE_Allocator *message_block_allocator)
{
//...... 略去无关代码

if (this->data_block_ != 0)
    {
      this->data_block_->release ();
      this->data_block_ = 0;
    }

if (db == 0)
    {
      if (data_block_allocator == 0)
      ACE_ALLOCATOR_RETURN (data_block_allocator,
                              ACE_Allocator::instance (),
                              -1);

      ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_ALLOC);

      
      ACE_NEW_MALLOC_RETURN (db,
                           static_cast<ACE_Data_Block *> (
                               data_block_allocator->malloc (sizeof (ACE_Data_Block))),
                           ACE_Data_Block (size,
                                             msg_type,
                                             msg_data,// =null
                                             allocator_strategy,
                                             locking_strategy,
                                             flags, // =ACE_Message_Block::DONT_DELETE
                                             data_block_allocator),
                           -1);
      ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR);
    }

// Reset the data_block_ pointer.
this->data_block (db);
// If the data alloc failed, the ACE_Data_Block ctor can't relay
// that directly. Therefore, need to check it explicitly.
if (db->size () < size)
    return -1;
return 0;
}


ACE_Data_Block::ACE_Data_Block (size_t size,
                              ACE_Message_Block::ACE_Message_Type msg_type,
                              const char *msg_data,
                              ACE_Allocator *allocator_strategy,
                              ACE_Lock *locking_strategy,
                              ACE_Message_Block::Message_Flags flags,
                              ACE_Allocator *data_block_allocator)
: type_ (msg_type),
    cur_size_ (0),          // Reset later if memory alloc'd ok
    max_size_ (0),
    flags_ (flags), // =ACE_Message_Block::DONT_DELETE
    base_ (const_cast <char *> (msg_data)), //base = 0
    allocator_strategy_ (allocator_strategy),
    locking_strategy_ (locking_strategy),
    reference_count_ (1),
    data_block_allocator_ (data_block_allocator)
{
ACE_TRACE ("ACE_Data_Block::ACE_Data_Block");
ACE_FUNCTION_TIMEPROBE (ACE_DATA_BLOCK_CTOR2_ENTER);

// If the user didn't pass one in, let's use the
// <ACE_Allocator::instance>.
if (this->allocator_strategy_ == 0)
    ACE_ALLOCATOR (this->allocator_strategy_,
                   ACE_Allocator::instance ());

if (this->data_block_allocator_ == 0)
    ACE_ALLOCATOR (this->data_block_allocator_,
                   ACE_Allocator::instance ());

if (msg_data == 0)// msg_data = 0,为base_分配内存
    ACE_ALLOCATOR (this->base_,
                   (char *) this->allocator_strategy_->malloc (size));
    // ACE_ALLOCATOR returns on alloc failure...

// The memory is legit, whether passed in or allocated, so set the size.
this->cur_size_ = this->max_size_ = size;
}

ACE_Data_Block::~ACE_Data_Block (void)
{
// Sanity check...
ACE_ASSERT (this->reference_count_ <= 1);

// Just to be safe...
this->reference_count_ = 0;

if (ACE_BIT_DISABLED (this->flags_,
                        ACE_Message_Block::DONT_DELETE))   //this->flags_=ACE_Message_Block::DONT_DELETE
    {
      this->allocator_strategy_->free ((void *) this->base_); //不会执行该语句,base_指向的内存没有释放,泄漏!
      this->base_ = 0;
    }
}

peakzhang 发表于 2007-12-21 21:54:47

ACE_Message_Block的数据直接指向了参数中const char *data这块内存,这块内存不是由ACE_Message_Block创建的,所以不必释放。

peakzhang 发表于 2007-12-21 21:54:57

不同意楼上的。是base_的内存泄漏,不是data。

在ACE_Data_Block的构函中有如下语句:

if (msg_data == 0)// 此时 msg_data = 0,为base_分配内存
    ACE_ALLOCATOR (this->base_,
                   (char *) this->allocator_strategy_->malloc (size));
    // ACE_ALLOCATOR returns on alloc failure...

但在ACE_Data_Block的析构函数中,由于ACE_Data_Block标志为ACE_Message_Block::DONT_DELETE,
故不会释放base_的内存!

peakzhang 发表于 2007-12-21 21:55:02

base_就是指向的data

ACE_Data_Block::ACE_Data_Block (size_t size,
                              ACE_Message_Block::ACE_Message_Type msg_type,
                              const char *msg_data,
                              ACE_Allocator *allocator_strategy,
                              ACE_Lock *locking_strategy,
                              ACE_Message_Block::Message_Flags flags,
                              ACE_Allocator *data_block_allocator)
: type_ (msg_type),
    cur_size_ (0),          // Reset later if memory alloc'd ok
    max_size_ (0),
    flags_ (flags), // =ACE_Message_Block::DONT_DELETE
    base_ (const_cast <char *> (msg_data)), //base = 0
    allocator_strategy_ (allocator_strategy),
    locking_strategy_ (locking_strategy),
    reference_count_ (1),
    data_block_allocator_ (data_block_allocator)

peakzhang 发表于 2007-12-21 21:55:09

在ACE_Data_Block的构函初始化列表中base_就是指向的data

//(base_ (const_cast <char *> (msg_data)), )
但在构造函数体中有下列语句

if (msg_data == 0)// msg_data = 0,为base_分配内存
    ACE_ALLOCATOR (this->base_,
                   (char *) this->allocator_strategy_->malloc (size));
这样如果data为空(也就是msg_data 为空),会重新为base_分配内存,此时base_和data

已经不一样了。

peakzhang 发表于 2007-12-21 21:55:17

ACE_Message_Block::ACE_Message_Block (const char *data,
                                    size_t size,
                                    unsigned long priority)
data为空的话,size也应该为0啊, malloc(0)没事

peakzhang 发表于 2007-12-21 21:55:22

如果是这样,就不会有问题了!但客户要遵守该约定:data为空,size也应该为0
页: [1]
查看完整版本: ACE_Data_Block的内存泄漏,请大家指教!