双端队列问题:map<..., deque<> >失败了,但是向量和列表却没有?

发布于 2024-12-02 13:09:16 字数 3827 浏览 1 评论 0 原文

我有一个代码:

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指针)而导致程序崩溃的问题。仅当映射包含双端队列时才会发生这种情况,并且当存在列表或向量时一切正常。可能是什么?

这是我使用双端队列时的内存问题。 Insert 调用一堆复制构造函数。 另外,我还有一些 someClass 属性,在将其复制到内存后,如下所示:

0x00959B48 00 00 00 00 00 00 00 00

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

0x00959B48 f0 9b 95 00 00 00 00 00

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

0x00959B0F fd 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 00 00 00 00 00

最后回到我们最后的内容

0x00959B48 f0 9b 95 00 00 00 00 00

所以我们所面临的是对象被销毁,内存被覆盖,并且对象返回到充满垃圾的同一内存(可能是地图数据)。 我用列表和向量替换了双端队列,两者都工作得很好。 所以有一个问题:双端队列到底发生了什么,或者我可能做错了,我应该如何解决这个问题?

编辑:这是功能代码:

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
                }
        }
    }
}

这是一些类:

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;
    };
};

I have a code:

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());

that intended to merge two someMap. But there is a problem that crashes program due to memory errors(0xcdcdcdcd pointer). And that is happening only if map contains deques, and everything works fine when there are lists or vectors. What might it be?

Here is memory problem when I'm using deques. Insert calls a bunch of copy-constructors.
Also I have some property of someClass that after copying points to memory that looks like this:

0x00959B48 00 00 00 00 00 00 00 00

Right before error occures(in copy-constructor of someClass), this field(of copying object) points here(same address):

0x00959B48 f0 9b 95 00 00 00 00 00

There is something that looks like address not far away from here(0x00959B48):

0x00959B0F fd ab ab ab ab ab ab ab

Other pointers to that one copying object also point on invalid memory(0xcdcdcdcd <- thanks MSVS in debug mode for pointing that out).

Then I set memory write breakpoint for that address(0x00959B48) and thats what I found:

 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...

So what we have is destruction of that object.

 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[]

and so on value several times changes inside STL code like this:

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

into this

0x00959B48 08 f6 12 00 00 00 00 00

and finally back to what we have at the end

0x00959B48 f0 9b 95 00 00 00 00 00

So what we have is object being destroyed, memory overwritten, and object goes back to the same memory filled with garbage(which is probably map data).
I substituted deque with list and vector and both worked fine.
So there is a question: what the hell happened with deque, or maybe I'm doing this wrong way and how should I resolve this?

Edit: Here is function code:

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
                }
        }
    }
}

Here is someClass:

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;
    };
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心如荒岛 2024-12-09 13:09:16

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

it = container.insert (it, element);

而不仅仅是:

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

I think you are invalidating the iterators with insert. For most containers, you have to re-set the iterator value after each insertion, i.e.:

it = container.insert (it, element);

instead of just:

container.insert (it, element);  // it may not be valid anymore
最美的太阳 2024-12-09 13:09:16

您在 someClass 中定义了复制构造函数,但没有定义赋值运算符。

一旦对象发生“有趣”的事情,您就会泄漏旧值,然后有两个对象指向同一个complexClass。当其中第一个删除其指针时,所有副本都将具有无效指针!

尝试复制这些无效对象之一将会破坏您所看到的方式。

You have defined a copy constructor in someClass but no assignment operator.

As soon as something "interesting" happens to the objects, you will leak the old values and then have two objects pointing to the same complexClass. When the first of those deletes its pointer, all the copies will have invalid pointers!

Trying to copy one of these invalid objects will break the way you have seen.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文