在映射中擦除时崩溃(c++)

crashing when erasing in a map (C++)

本文关键字:c++ 崩溃 映射 擦除      更新时间:2023-10-16

这部分代码总是崩溃。我不明白这次撞车的原因。我所做的就是在循环中设置一些指针。如果我评论这个循环,一切都会好起来的。很奇怪. .底部的代码是发生崩溃的地方。我不知道调用了什么析构函数,也不知道为什么我的程序崩溃了。

    typedef std::set<IDrawable**> TDrawableList;
        typedef std::map<std::string, TDrawableList> THashLoad;
//  ...
    THashLoad::iterator itLoad =  gpMapRenderer->m_unloadedCells.find(file.substr(6, file.length()));
        if (itLoad != gpMapRenderer->m_unloadedCells.end())
        {
                TDrawableList::iterator itCells = itLoad->second.begin();
                TDrawableList::iterator itCellsEnd = itLoad->second.end();
                for (; itCells != itCellsEnd; ++itCells)
                {
                        **itCells = (IDrawable*)itHashPics->second.pImg;
                }
                gpMapRenderer->m_unloadedCells.erase(itLoad);  // < --- CRASH
        }
    // ... 
    // _construct.h
    // ...
template <class _Tp>
inline void _Destroy(_Tp* __pointer) {
# if _MSC_VER >= 1010
  __pointer;
# endif    // _MSC_VER >= 1000
# ifdef _STLP_TRIVIAL_DESTRUCTOR_BUG
  typedef typename __type_traits<_Tp>::has_trivial_destructor _Trivial_destructor;
  __destroy_aux(__pointer, _Trivial_destructor());
# else
#  if ( defined (__BORLANDC__) && ( __BORLANDC__ < 0x500 ) )
    __pointer->_Tp::~_Tp();
#  else
    __pointer->~_Tp(); // < ---- CRASH
#  endif
# endif
# ifdef _STLP_DEBUG_UNINITIALIZED
        memset((char*)__pointer, _STLP_SHRED_BYTE, sizeof(_Tp));
# endif
}

注:我的程序是单线程的。

谢谢。更新:

class IDrawable
{
public:
    virtual ~IDrawable() {};
    virtual void Draw(const CIwSVec2& pos) = 0;
    virtual void Draw(const CIwSVec2& pos, const CIwSVec2& size) { IwAssert(IDRAWABLE, "Not Implemented");};
};

所以这里是我如何添加到m_unloaddcells:

void MapRenderer::AddCellToUnloadedList(const std::string& filename, IDrawable** pElement)
{
    THashLoad::iterator itLoad = m_unloadedCells.find(filename);
    if (itLoad != m_unloadedCells.end())
        itLoad->second.insert(pElement);
    else
    {
        std::set<IDrawable**> _set;
        _set.insert(pElement);
        m_unloadedCells.insert(make_pair(filename, _set));
    }
}

和代码中的某处:

AddCellToUnloadedList(filenameToLoad, &itHashCells->second[index].drawingElement[i].pDrawable)

itHashcells:

typedef std::map<int, std::vector<Cell2> > THashCells;
THashCells itHashCells;

Cell2:

enum eDrawableType
{
    DTYPE_Sprite = 0,
    DTYPE_Animation
};
struct DrawingElement
{
    eDrawableType type;
    IDrawable* pDrawable;
};
struct Cell2
{
    Cell2()
    {
        drawingElement.reserve(10);
    }
    int location;
    int x, y;
    std::vector<DrawingElement> drawingElement;
    MinimapTileInfo minimap_tile_info[10];
};

问题似乎在这一行:

**itCells = (IDrawable*)itHashPics->second.pImg;

not in erase()。试着把它注释掉看看。
我认为问题是你初始化指针到2个向量内的数据结构,虽然我看到你在Cell2中保留10个元素,但不清楚你是否在其中没有超过10个元素或在itHashCells中保留足够的元素。所以如果你插入足够多的元素到任何一个矢量中使它们重新分配空间那么gpMapRenderer-> m_unloaddcells

中的指针就会失效

我建议花时间重构你的代码,尽量避免使用指针对指针,或者至少使用不会使它们无效的数据结构。当前状态的代码不可维护。

你也可以重写这段代码:

void MapRenderer::AddCellToUnloadedList(const std::string& filename, IDrawable** pElement)
{
    THashLoad::iterator itLoad = m_unloadedCells.find(filename);
    if (itLoad != m_unloadedCells.end())
        itLoad->second.insert(pElement);
    else
    {
        std::set<IDrawable**> _set;
        _set.insert(pElement);
        m_unloadedCells.insert(make_pair(filename, _set));
    }
}

:

void MapRenderer::AddCellToUnloadedList(const std::string& filename, IDrawable** pElement)
{
    m_unloadedCells[ filename ].insert( pElement );
}