deque的问题:map<...,deque<> >失败,但向量和列表不是?

Problem with deque: map<..., deque<> > fails, but vector and list aren't?

本文关键字:lt deque gt 列表 向量 问题 失败 map      更新时间:2023-10-16
我有一个代码:
typedef map<Coordinate3D, deque<someClass > > someMap;
someMap *newEM;
someMap::iterator iter;
//...
(*newEM)[iter->first].insert((*newEM)[iter->first].end(),
                             iter->second.begin(), iter->second.end());

意图合并两个someMap。但有一个问题,崩溃程序由于内存错误(0xcdcdcdcd指针)。这只有在map包含deque时才会发生,当有列表或向量时一切都很好。会是什么呢?

这是内存问题,当我使用deque。Insert调用一堆复制构造函数。另外,我有一些属性someClass,复制点到内存后,看起来像这样:

0x00959B48 00 000 000 000 000 000 000 000 000 000 000

在错误发生之前(在someClass的复制构造函数中),这个字段(复制对象)指向这里(相同的地址):

0x00959B48 f0 9b 95 00 000 000 000 000 000

有一个看起来像地址的东西离这里不远(0x00959B48):

0x00959B0F fd ab ab ab ab ab ab ab ab

指向该复制对象的其他指针也指向无效内存(0xcdcdcdcd <-感谢调试模式中的MSVS指出这一点)。

然后我为该地址(0x00959B48)设置内存写入断点,这就是我发现的:

 msvcr100d.dll!memset...//breakpoint activated here
 msvcr100d.dll!_free_dbg_nolock...
 msvcr100d.dll!_free_dbg...
 msvcr100d.dll!operator delete...
 program.exe!someClass::~someClass()  Line 294 + 0x21 bytes C++
 program.exe!std::swap...
 program.exe!std::iter_swap...
 program.exe!std::_Reverse...
 program.exe!std::reverse...
 program.exe!std::deque<...>::_Insert...
 program.exe!std::deque<...>::insert...

所以我们得到的是那个对象的销毁。

 msvcr100d.dll!memset...
 msvcr100d.dll!_heap_alloc_dbg_impl...
 msvcr100d.dll!_nh_malloc_dbg_impl...
 msvcr100d.dll!_nh_malloc_dbg...
 msvcr100d.dll!operator new...
 program.exe!std::_Allocate<std::_Container_proxy>...
 program.exe!std::allocator<std::_Container_proxy>::allocate...
 program.exe!std::_Deque_val...
 program.exe!std::deque<..>::deque<..> >()
 program.exe!std::map<...::operator[]

等值在STL代码中多次更改,如下所示:

if (_Right._Myproxy != 0)//<--breaks here
        _Right._Myproxy->_Mycont = (_Container_base12 *)&_Right;

0x00959B48 08 f6 12 000 000 000 000 000 000

最后回到我们在末尾的

0x00959B48 f0 9b 95 00 000 000 000 000 000

所以我们得到的是对象被销毁,内存被覆盖,对象返回到充满垃圾(可能是映射数据)的相同内存。我用列表和向量替换了deque,两者都工作得很好。那么问题来了,deque到底是怎么回事,还是我做错了,我该如何解决?

编辑:这里是函数代码:

void MergeEffectsMaps(EffectsMap **dest, EffectsMap *src) {
    EffectsMap *newEM = *dest;
    EffectsMap::iterator findIter;
    for (EffectsMap::iterator iter = src->begin();
            iter != src->end(); iter++) {
        findIter = newEM->find(iter->first);
        if (findIter != newEM->end()) {//exists
            if (!iter->second.empty())
                findIter->second.insert(findIter->second.end(),
                    iter->second.begin(), iter->second.end());
        } else {
            if (!iter->second.empty()){
                (*newEM)[iter->first];
                (*newEM)[iter->first].insert((*newEM)[iter->first].end(),
                    iter->second.begin(), iter->second.end());//<----problem
                }
        }
    }
}

下面是someeclass:

class someClass {
public:
    complexClass1 *value1;
    complexClass2 *value2;
    float value3;
    int value4;
    someClass(){
     value1=new complexClass1 ();
     value2=new complexClass2 ();
     value3=0;
     value4=0;
    };
    someClass(const FieldEffect& cp_val){
     value1=new complexClass1 (*cp_val.value1);//copy-constructor
     value2=new complexClass2 (*cp_val.value2);
     value3=cp_val.value3;
     value4=cp_val.value4;
    };
    ~someClass(){
     delete value1;
     delete value2;
    };
};

我认为您使用insert使迭代器无效。对于大多数容器,每次插入后都必须重新设置迭代器的值,例如:

it = container.insert (it, element);

而不是:

container.insert (it, element);  // it may not be valid anymore

someClass中定义了复制构造函数,但没有赋值操作符。

一旦对象发生了一些"有趣的"事情,您将泄漏旧值,然后有两个对象指向相同的complexClass。当第一个对象删除它的指针时,所有的副本都将拥有无效的指针!

试图复制这些无效对象中的一个将破坏您所看到的方式。