S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

复杂的逻辑的BUG

Posted on 2009-03-04 08:48 S.l.e!ep.¢% 阅读(1722) 评论(4)  编辑 收藏 引用 所属分类: C++

在一个界面中的按钮事件中需要向 所有在线的服务器 发送信息

void Dialog::Button_Click()
{

    map <unsigned long, CServer*>::iterator iter;
    for ( iter = m_OnLineServers.begin(); iter != m_OnLineServers.end(); iter++ )
    {
         iter->second->sendMsg();
    }

}

所有 在线服务器 都存放在  m_OnLineServers  这个列表中,这个列表是一个 std::map
sendMsg()   内部又调用了 SOCKET 函数的 send

当 send 执行失败时,  会通知 Dialog 的  OnServerClose() 事件
void Dialog::OnServerClose(int nIndex)
{
  map <unsigned long, CServer*>::iterator iter   = m_OffLineServers.find(nIndex);
  if ( iter != m_OffLineServers.end() )
  {
   m_OffLineServers.insert(make_pair<unsigned long, CServer*>(nIndex, iter_find->second));
   m_OnLineServers.erase(nIndex);
  }


OnServerClose() 事件需要把 CServer 从 Online 列表中删除, 跟着添加到 OffLine 列表


结合起来看,就会出现在同一条线程中

遍历 map
{
    删除 map 元素
}

google了一下,网友们在遍历的过程中删除元素的方法是
for(iter = list.begin(); iter != list.end();)
{
    if (shouldDelete(*iter))
       iter = list.erase(iter);
    else
       ++iter;
}


似乎能解决问题,

但从上面的逻辑来看, 遍历跟删除, 分别是在两个不同的类, 这样一来逻辑就复杂多了
通常BUG都是因为复杂的逻辑而产生的。

Feedback

# re: 复杂的逻辑的BUG  回复  更多评论   

2009-03-04 09:07 by LOGOS
遍历的过程很可能会调用一些删除操作,而且调用得很隐含
这样的情况是有的,而且不算什么异常的事情
这种情况下采用异步的删除机制就可以了

# re: 复杂的逻辑的BUG  回复  更多评论   

2009-03-04 09:19 by qtopia
发送消息的时候,建立一份m_onlineServers的拷贝,在拷贝中发送消息

# re: 复杂的逻辑的BUG  回复  更多评论   

2009-03-04 09:37 by zuhd
只要是同一份内存数据,在同一个线程中,就不会出现所谓冲突的问题,仔细检查下代码,看看,你后面说的遍历删除map的问题是防止删除最后一个元素的时候越界

# re: 复杂的逻辑的BUG  回复  更多评论   

2009-03-04 15:13 by Nobody
迭代器遍历的时候,如果对容器添加或者删除元素,容易造成混乱。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理