【问题标题】:c++ boost map program crash after erasec ++ boost map程序在擦除后崩溃
【发布时间】:2014-11-06 00:41:00
【问题描述】:

我有一个问题,不知道如何正确解决它或为什么会出现错误。

我的问题: 我有 1 个循环,每 2 秒执行一个函数。该函数执行 for() 函数并擦除剩余时间为 0 的所有条目。如果剩余时间不为 0,则它将减少 2000(2 秒)。

但是在删除一个条目后,程序崩溃了……

提升地图:

boost::unordered_map<unsigned int, sBUFF_INFO*> p_BuffInfo;

从 2 秒循环执行的函数

void CSkill::DecreaseAllBuffRemTime()
{
    for( itertype(p_BuffInfo) it = p_BuffInfo.begin(); it != p_BuffInfo.end(); it++ )
    {
        sBUFF_INFO* buff = it->second;
        if(buff != NULL)
        {
            if(buff->dwTimeRemaining <= 0)
            {
                this->DelPcBuffInfo(buff->tblidx)
            }else{
                buff->dwTimeRemaining -= 2000;
            }
        }
    }
}

DelPcBuffInfo 函数:

void CSkill::DelPcBuffInfo(unsigned int tblidx)
{
    p_BuffInfo.erase(tblidx);
}

现在 DelPcBuffInfo 执行后程序崩溃。

在这一行它崩溃了:

sBUFF_INFO* buff = it->second;

调试时:

GameServer.exe 中 0x00578e0f 处未处理的异常:0xC0000005: 访问冲突读取位置 0xdddddd9.

it + node_ = hash_ CXX0030;错误:无法计算表达式

我真的不明白为什么会出现这个错误..

编辑: 如果我在 this->DelPcBuffInfo(buff->tblidx) 之后添加“return”,那么程序不会崩溃..

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    在容器中添加或删除项目通常会使您的迭代器失效。检查 unordered_map 迭代器的文档或在这里:Iterator invalidation in boost::unordered_map

    【讨论】:

      【解决方案2】:

      正确的成语是

      for( itertype(p_BuffInfo) it = p_BuffInfo.begin(); it != p_BuffInfo.end(); )
      {
          sBUFF_INFO* buff = it->second;
          if(buff != NULL)
          {
              if(buff->dwTimeRemaining <= 0)
              {
                  it = this->DelPcBuffInfo(buff->tblidx)
              }else{
                  buff->dwTimeRemaining -= 2000;
                  it++;
              }
          }
      }
      

      即不要在循环中递增。如果您不删除,则改为递增,否则删除操作会返回新的迭代器。这就是为什么 remove 返回一个指向下一个元素的迭代器

      这是由令人敬畏的斯科特迈尔斯提供的

      【讨论】:

      • 谢谢。此行出错 it = this->DelPcBuffInfo(buff->tblidx)。 "没有找到使用 'void' 类型的右手操作数的运算符
      • 这个成语是在迭代器上擦除,这不是他在做什么
      • delxxx 闻起来像擦除,标题写着“擦除后 c++ boost map 程序崩溃”
      • @pm100 他确实擦除了键,返回计数
      • 如果buff==NULL,它也会陷入无限循环
      【解决方案3】:

      添加到现有答案中,指出擦除迭代器习语:您崩溃的原因是迭代器 it 由于删除了元素而失效。因此,(无效)运算符的增量会导致未定义的行为,它将指向某个任意内存块。取消引用“迭代器”会使您的程序崩溃。

      为避免此问题,请应用其他答案中演示的习语,即 * 使用 erase 的迭代器版本。它返回一个迭代器到 next 元素(可能是end()) * 使用此erase 的返回值作为it 的新值。由于它已经指向下一个元素,所以 not 再次递增(否则,如果it 已经指向地图的末尾,您可能会跳过地图中的元素或导致未定义的行为。 * 仅当您没有擦除元素时,您自己增加迭代器。

      注意:如果您的意图是在从映射中删除时完全删除 sBUFF_INFO 元素,则您的程序会显示内存泄漏。从映射中擦除指针不会删除指向的内存。您需要自己删除指针(或使用适当的智能指针)。

      【讨论】:

        【解决方案4】:
        void CSkill::DecreaseAllBuffRemTime()
        {
            auto it = p_BuffInfo.begin();
            while( it != p_BuffInfo.end() )
            {
                sBUFF_INFO* buff = it->second;
                if(buff)
                {
                    if(buff->dwTimeRemaining <= 0)
                    {
                        // probably delete buff too
                        it = p_BuffInfo.erase(it);
                    } else {
                        buff->dwTimeRemaining -= 2000;
                        ++it;
                    }
                } else {
                    ++it;
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-24
          • 1970-01-01
          • 2021-03-02
          • 2012-04-16
          • 2012-05-20
          • 2012-03-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多