找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 6720|回复: 10

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

[复制链接]
发表于 2009-12-1 15:47:30 | 显示全部楼层 |阅读模式
大家帮忙看下这个问题:
#0  0x0020f7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x002547a5 in raise () from /lib/tls/libc.so.6
#2  0x00256209 in abort () from /lib/tls/libc.so.6
#3  0x0028871a in __libc_message () from /lib/tls/libc.so.6
#4  0x0028f99c in _int_malloc () from /lib/tls/libc.so.6
#5  0x00291401 in malloc () from /lib/tls/libc.so.6
#6  0x001b1456 in operator new () from /usr/lib/libstdc++.so.6
#7  0x001b1508 in operator new[] () from /usr/lib/libstdc++.so.6
#8  0x006db123 in ACE_New_Allocator::malloc (this=0x79a3a0, nbytes=80) at ../../ace/Malloc_Allocator.cpp:118
#9  0x006dcdcc 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, [email=execution_time=@0x80fd590]execution_time=@0x80fd590[/email], [email=deadline_time=@0x80fd5e0]deadline_time=@0x80fd5e0[/email], 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, [email=execution_time=@0x80fd590]execution_time=@0x80fd590[/email], [email=deadline_time=@0x80fd5e0]deadline_time=@0x80fd5e0[/email], 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 编辑 ]
发表于 2009-12-1 16:02:28 | 显示全部楼层
这么简单的用法应该不会出错吧。
后来new出来的ACE_Message_Block 正常么?
那个size是不是 ACE_Data_Block 还没完成初始化的时候的值(-1)?
可以仔细看看ACE_Message_Block::init_i的代码
 楼主| 发表于 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, [email=execution_time=@0x80fd590]execution_time=@0x80fd590[/email], [email=deadline_time=@0x80fd5e0]deadline_time=@0x80fd5e0[/email], 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, [email=execution_time=@0x80fd590]execution_time=@0x80fd590[/email], [email=deadline_time=@0x80fd5e0]deadline_time=@0x80fd5e0[/email], 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;
}




#9  0x006dcdcc 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 编辑 ]
发表于 2009-12-1 21:52:23 | 显示全部楼层
多线程这样
ACE_Message_Block *mb = 0;
ACE_NEW (mb, ACE_Message_Block (80));
应该没问题,mb是auto变量。但如果mb是共享的一个指针,比如是成员变量。肯定有问题。
如果问题不可重现,很可能是多线程问题。
可以加点print语句,看一下出问题时size在哪里开始变的。例如
  1. // size = ?
  2. ACE_NEW_MALLOC_RETURN (db,                                             
  3.                              static_cast<ACE_Data_Block *> (
  4.                                data_block_allocator->malloc (sizeof (ACE_Data_Block))),
  5.                              ACE_Data_Block (size,                                                      
  6.                                              msg_type,
  7.                                              msg_data,
  8.                                              allocator_strategy,
  9.                                              locking_strategy,
  10.                                              flags,
  11.                                              data_block_allocator),
  12.                              -1);
复制代码
  1. // size = ?
  2. if (msg_data == 0)
  3.     {
  4.       ACE_ALLOCATOR (this->base_,
  5.                      (char *) this->allocator_strategy_->malloc (size));           
复制代码

[ 本帖最后由 wishel 于 2009-12-1 21:54 编辑 ]
发表于 2009-12-1 21:53:50 | 显示全部楼层
这个size比较有意思,-1是4294967296吧,差了24
 楼主| 发表于 2009-12-2 03:28:18 | 显示全部楼层

回复 #5 wishel 的帖子

mb是auto变量,不是共享的。
我怀疑某处可能有溢出造成,就是不好找。
各单元测试没有问题,valgrind检查也没发现问题。(跑了很多遍,逻辑分支也很多)
怕是某种情况下累积导致触发问题,但是没规律,不重现,很是头疼。
这玩意终归是个隐患。
版主有什么好办法吗?
发表于 2009-12-2 16:00:42 | 显示全部楼层
难重现的问题最头疼。
我一般是加print语句,不出问题时候就是多打点东西而已,但一旦出问题时打印的信息就有价值了。
可以在程序中各处加一些print语句,先找出出问题时size最早的变化位置。
 楼主| 发表于 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 编辑 ]
发表于 2009-12-3 15:40:47 | 显示全部楼层
原帖由 denis_lan 于 2009-12-2 22:57 发表
通过core可以看到size发生变化的位置,因为实在ACE的代码中。所以通过打印size的变化过程没有什么实际意义。我的意思是说ACE_NEW这个Message_Block时就进入ACE的代码了,实际发生变化的位置我上面也指出来了,所以我在其他 ...

core可以看到变化了的位置,但这个位置不一定是最早发生变化的位置。
malloc(size)的时候core dump了,但这个size在之前被多次传递。也就是说是问题体现点而不一定是问题发生点。
发表于 2009-12-3 18:29:28 | 显示全部楼层
我的意思是,形参和实参是不同的,实参是以传值的方式压栈的,它和实参分别有不同的存储地址。
#9  0x006dcdcc 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是没有问题的)是否已经先出问题了。
所谓出问题也就是它所在的内存被修改了,由于都是栈上变量,不会是多线程问题,有可能是缓冲区溢出造成的。缓冲区溢出问题也有难以重现的特征。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-23 13:39 , Processed in 0.031105 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表