denis_lan 发表于 2009-12-1 15:47:30

创建ACE_Message_Block时size为什么发生了变化?

大家帮忙看下这个问题:
#00x0020f7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#10x002547a5 in raise () from /lib/tls/libc.so.6
#20x00256209 in abort () from /lib/tls/libc.so.6
#30x0028871a in __libc_message () from /lib/tls/libc.so.6
#40x0028f99c in _int_malloc () from /lib/tls/libc.so.6
#50x00291401 in malloc () from /lib/tls/libc.so.6
#60x001b1456 in operator new () from /usr/lib/libstdc++.so.6
#70x001b1508 in operator new[] () from /usr/lib/libstdc++.so.6
#80x006db123 in ACE_New_Allocator::malloc (this=0x79a3a0, nbytes=80) at ../../ace/Malloc_Allocator.cpp:118
#90x006dcdcc in ACE_Data_Block (this=0x9f93c970, size=4294967272, msg_type=1, msg_data=0x0, allocator_strategy=0x0, locking_strategy=0x0, flags=0,
    data_block_allocator=0x79a3a0) at ../../ace/Message_Block.cpp:368
#10 0x006dd738 in ACE_Message_Block::init_i (this=0x9fd86030, size=80, msg_type=1, msg_cont=0x0, msg_data=0x0, allocator_strategy=0x0,
    locking_strategy=0x0, flags=0, priority=0, execution_time=@0x80fd590, deadline_time=@0x80fd5e0, db=0x9f93c970, data_block_allocator=0x79a3a0,
    message_block_allocator=0x0) at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/new:92
#11 0x006de21b in ACE_Message_Block (this=0x9fd86030, size=80, msg_type=1, msg_cont=0x0, msg_data=0x0, allocator_strategy=0x0, locking_strategy=0x0,
    priority=0, execution_time=@0x80fd590, deadline_time=@0x80fd5e0, data_block_allocator=0x0, message_block_allocator=0x0)
    at ../../ace/Message_Block.cpp:453

为什么构造ACE_Message_Block时穿进去的size=80,走到ACE_Message_Block::init_i 时也是size=80,但是在init_i中创建ACE_Data_Block时却变成了size=4294967272.

创建就用了
ACE_Message_Block *mb = 0;
ACE_NEW (mb, ACE_Message_Block (80));

[ 本帖最后由 denis_lan 于 2009-12-1 15:51 编辑 ]

wishel 发表于 2009-12-1 16:02:28

这么简单的用法应该不会出错吧。
后来new出来的ACE_Message_Block 正常么?
那个size是不是 ACE_Data_Block 还没完成初始化的时候的值(-1)?
可以仔细看看ACE_Message_Block::init_i的代码

denis_lan 发表于 2009-12-1 16:24:15

谢谢版主这么快回答。
是的,就是这么简单的用法。根据core_dump看,就是由于size发生了变化(变成了很大的数),导致new失败(abort)

ACE_Message_Block (size=80) :
11 0x006de21b in ACE_Message_Block (this=0x9fd86030, size=80, msg_type=1, msg_cont=0x0, msg_data=0x0, allocator_strategy=0x0, locking_strategy=0x0,
    priority=0, execution_time=@0x80fd590, deadline_time=@0x80fd5e0, data_block_allocator=0x0, message_block_allocator=0x0)
    at ../../ace/Message_Block.cpp:453

ACE_Message_Block::init_i (size=80)
#10 0x006dd738 in ACE_Message_Block::init_i (this=0x9fd86030, size=80, msg_type=1, msg_cont=0x0, msg_data=0x0, allocator_strategy=0x0,
    locking_strategy=0x0, flags=0, priority=0, execution_time=@0x80fd590, deadline_time=@0x80fd5e0, db=0x9f93c970, data_block_allocator=0x79a3a0,
    message_block_allocator=0x0) at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/new:92

在init_i 里创建ACE_Data_Block时就变了
int
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)
{
ACE_TRACE ("ACE_Message_Block::init_i");
ACE_FUNCTION_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_ENTER);
this->rd_ptr_ = 0;
this->wr_ptr_ = 0;
this->priority_ = priority;
#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
this->execution_time_ = execution_time;
this->deadline_time_ = deadline_time;
#else
ACE_UNUSED_ARG (execution_time);
ACE_UNUSED_ARG (deadline_time);
#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
this->cont_ = msg_cont;
this->next_ = 0;
this->prev_ = 0;
this->message_block_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);
      // Allocate the <ACE_Data_Block> portion, which is reference
      // counted.
    ACE_NEW_MALLOC_RETURN (db,                                                // 这里生成ACE_Data_Block
                           static_cast<ACE_Data_Block *> (
                               data_block_allocator->malloc (sizeof (ACE_Data_Block))),
                           ACE_Data_Block (size,                                                      
                                             msg_type,
                                             msg_data,
                                             allocator_strategy,
                                             locking_strategy,
                                             flags,
                                             data_block_allocator),
                           -1);
      ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR);
      // Message block initialization may fail, while the construction
      // succeds.Since ACE may throw no exceptions, we have to do a
      // separate check and clean up, like this:
      if (db != 0 && db->size () < size)
      {
          db->ACE_Data_Block::~ACE_Data_Block();// placement destructor ...
          data_block_allocator->free (db); // free ...
          errno = ENOMEM;
          return -1;
      }
    }
// Reset the data_block_ pointer.
this->data_block (db);
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),
    base_ (const_cast <char *> (msg_data)),
    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)
    {
      ACE_ALLOCATOR (this->base_,
                     (char *) this->allocator_strategy_->malloc (size));         // 根据core_dump看,这里size就不对了
#if defined (ACE_INITIALIZE_MEMORY_BEFORE_USE)
      (void) ACE_OS::memset (this->base_,
                           '\0',
                           size);
#endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
    }
// ACE_ALLOCATOR returns on alloc failure but we cant throw, so setting
// the size to 0 (i.e. "bad bit") ...
if (this->base_ == 0)
    {
      size = 0;
    }

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

          errno = ENOMEM;
          return -1;
      }
    }
// Reset the data_block_ pointer.
this->data_block (db);
return 0;
}




#90x006dcdcc in ACE_Data_Block (this=0x9f93c970, size=4294967272, msg_type=1, msg_data=0x0, allocator_strategy=0x0, locking_strategy=0x0, flags=0,
    data_block_allocator=0x79a3a0) at ../../ace/Message_Block.cpp:368


很奇怪。
另外,程序运行所在的服务器是每10分钟和一台时间服务器进行同步的,不知道这个有没有影响。
ACE_Message_Block是在一个函数内创建的,不是类成员,是一个独立的公共函数,有多个线程会调用,没有全局变量,静态变量。会可能导致这个问题吗?
而且不是可重现的,假如其他地方有溢出,有可能导致出现这个问题吗?

[ 本帖最后由 denis_lan 于 2009-12-1 16:41 编辑 ]

wishel 发表于 2009-12-1 21:52:23

多线程这样
ACE_Message_Block *mb = 0;
ACE_NEW (mb, ACE_Message_Block (80));
应该没问题,mb是auto变量。但如果mb是共享的一个指针,比如是成员变量。肯定有问题。
如果问题不可重现,很可能是多线程问题。
可以加点print语句,看一下出问题时size在哪里开始变的。例如 // size = ?
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,
                                             allocator_strategy,
                                             locking_strategy,
                                             flags,
                                             data_block_allocator),
                           -1);// size = ?
if (msg_data == 0)
    {
      ACE_ALLOCATOR (this->base_,
                     (char *) this->allocator_strategy_->malloc (size));         

[ 本帖最后由 wishel 于 2009-12-1 21:54 编辑 ]

wishel 发表于 2009-12-1 21:53:50

这个size比较有意思,-1是4294967296吧,差了24

denis_lan 发表于 2009-12-2 03:28:18

回复 #5 wishel 的帖子

mb是auto变量,不是共享的。
我怀疑某处可能有溢出造成,就是不好找。
各单元测试没有问题,valgrind检查也没发现问题。(跑了很多遍,逻辑分支也很多)
怕是某种情况下累积导致触发问题,但是没规律,不重现,很是头疼。
这玩意终归是个隐患。
版主有什么好办法吗?

wishel 发表于 2009-12-2 16:00:42

难重现的问题最头疼。
我一般是加print语句,不出问题时候就是多打点东西而已,但一旦出问题时打印的信息就有价值了。
可以在程序中各处加一些print语句,先找出出问题时size最早的变化位置。

denis_lan 发表于 2009-12-2 22:57:12

回复 #7 wishel 的帖子

通过core可以看到size发生变化的位置,因为实在ACE的代码中。所以通过打印size的变化过程没有什么实际意义。我的意思是说ACE_NEW这个Message_Block时就进入ACE的代码了,实际发生变化的位置我上面也指出来了,所以我在其他环节打印是没有意义的(况且size就是在ACE_NEW中指定的,我在#1楼的帖子里有)

[ 本帖最后由 denis_lan 于 2009-12-3 03:21 编辑 ]

wishel 发表于 2009-12-3 15:40:47

原帖由 denis_lan 于 2009-12-2 22:57 发表 http://www.acejoy.com/bbs/images/common/back.gif
通过core可以看到size发生变化的位置,因为实在ACE的代码中。所以通过打印size的变化过程没有什么实际意义。我的意思是说ACE_NEW这个Message_Block时就进入ACE的代码了,实际发生变化的位置我上面也指出来了,所以我在其他 ...

core可以看到变化了的位置,但这个位置不一定是最早发生变化的位置。
malloc(size)的时候core dump了,但这个size在之前被多次传递。也就是说是问题体现点而不一定是问题发生点。

wishel 发表于 2009-12-3 18:29:28

我的意思是,形参和实参是不同的,实参是以传值的方式压栈的,它和实参分别有不同的存储地址。
#90x006dcdcc in ACE_Data_Block (this=0x9f93c970, size=4294967272, msg_type=1, msg_data=0x0, allocator_strategy=0x0, locking_strategy=0x0, flags=0,data_block_allocator=0x79a3a0) at ../../ace/Message_Block.cpp:368
这句可以看出是ACE_Data_Block()中的实参size出了问题,但不能具体确定是否传来的形参size(它又是init_i中的实参size,init_i中的形参size是没有问题的)是否已经先出问题了。
所谓出问题也就是它所在的内存被修改了,由于都是栈上变量,不会是多线程问题,有可能是缓冲区溢出造成的。缓冲区溢出问题也有难以重现的特征。
页: [1] 2
查看完整版本: 创建ACE_Message_Block时size为什么发生了变化?