std :: map错误分配错误

时间:2013-07-19 08:04:07

标签: c++ stdmap bad-alloc

我正面临着std :: map的问题。由于未知原因,有时插入映射会导致“错误分配”异常。

以下是我用于插入地图的功能。

BOOL Add2WaitList(Object<LPVOID> *newObj)
{
    try
    {
        _set_se_translator( trans_func );
        m_syncWQ.Lock();
        if (m_waitingQueue.count(newObj->uid)>0)
        {
            m_syncWQ.Unlock();
            return FALSE;
        }
        m_waitingQueue[newObj->uid] = *newObj; <-- failing here
        m_syncWQ.Unlock();
        return TRUE;
    }
    catch(std::exception &ex){
        ...
    }
    catch(SE_Exception &e){
        ...
    }
    catch(...){
        ...
    }
}

有人可以告诉我如何解决这个问题吗?

注意:我无法确定重现它的步骤。

提前THX!

添加有关Object&amp;的详细信息图:

template <typename T>
struct Object{
public:
    void Kill()
    {
        if (response!=NULL)
            delete response;
        if (object!=NULL)
            delete object;
    }

    enum objType;
    std::string uid;
    enum status;
    double p;
    enum execType;
    T object;
    LPVOID response;
};

std::map<std::string,Object<LPVOID>> m_waitingQueue;

4 个答案:

答案 0 :(得分:2)

例外std::bad_alloc表示“operator new失败”。因此,operator newoperator*(我们对此一无所知)或地图的插入运算符(这种情况极有可能)被调用newObj

具体而言,当您使用某个参数k

在地图上调用operator[]
  

如果k与容器中任何元素的键不匹配,则   function使用该键插入一个新元素并返回一个引用   到它的映射值。请注意,这总是会增加容器   即使没有为元素分配映射值,也将大小加1   element是使用其默认构造函数构造的。

(如记录here)。

Map::operator[]为失败提供了强有力的保证:

Strong guarantee: if an exception is thrown, there are no changes in the container.

但不保证不会抛出异常(即它不提供无抛出保证)。

operator new抛出异常的原因可能不同。但是,这一切归结为:

throws bad_alloc if it fails to allocate storage.

那就是说,正如JamesKanze在评论中所说:

  

std :: bad_alloc的另一个可能原因是未定义的行为。如果   例如,他摧毁了自由空间舞台。而且实际上,   如果他真的耗尽内存,那么失败的分配   会有所不同如果系统地在这里,我会怀疑有问题   Object的复制构造函数,最重要的是。

意味着operator new由于程序其他部分的某些错误而无法分配存储空间。你可以通过在调用operator[]之前分配一个(非常)大数据块来调试他的null-assupmtion(统计学家会调用它)。如果虚拟分配没有失败,您可以很自信地说复制构造函数中存在错误。

答案 1 :(得分:2)

很明显,std :: map操作会导致问题

m_waitingQueue[newObj->uid] = *newObj;

它实际上是一个地图插入操作,它可能会在场景后面分配内存:How is a STL map allocated? Stack or Heap?。一个可能的原因是将内存导致分配给错误的分​​配异常:Bad allocation exceptions in C++

但是这段代码本身并没有导致解释幕后发生的事情。我认为需要更多与“m_waitingQueue”相关的信息,因为变量是全局的,在此函数之外可以做任何事情。

答案 2 :(得分:0)

operator new()功能无法找到请求的内容 记忆。可以从new表达式调用此函数,或 直接在std::map的分配器中。

您不会提供有关上下文的任何信息。该 真正的问题是:它是否总是在这一点上失败。 如果你真的没有内存(例如因为 一个内存泄漏),人们会期望它打到其他分配 好。其他可能性是你破坏了自由 在调用此函数之前的空间竞技场,或者存在 Object<LPVOID>的复制构造函数的问题 导致它要求无限的内存,或者破坏它 自由空间竞技场,以便下一次分配失败。你呢 将此物品复制到别处你通过它的事实 指针可能不会,在这种情况下,这将是 你会看到问题的地方。

编辑:

由于您已发布Object的代码:Object在哪里 你使用originate?指针通常指向什么, 如果它是动态分配的,那么如何管理删除?

因为Object没有用户定义的构造函数,这意味着 将存在指针包含随机垃圾的情况。 删除随机指针是腐败的一个很好的方法 自由空间竞技场。

另外:我注意到你看起来像同步 原语(Lock()Unlock())。还有什么地方 m_waitingQueue用过了吗?如果可以访问m_waitingQueue 一个不同的线程,所有对m_waitingQueue的访问必须是 使用相同的同步对象进行同步 (m_syncWQ)。试图在另一个中修改m_waitingQueue 你在这里修改它时的线程也可能导致 未定义的行为(队列对象在某处写入) 不应该的地方。)

答案 3 :(得分:0)

在内存不足之前,或许Add2WaitList(Object<LPVOID>)被调用数百万次。

在这种情况下,原因将在代码的其他地方 - 例如以无限循环或回归的形式。另一个可能的原因是,如果您的Object无意中获得了不同的uid。例如,uid从未初始化的数字派生时,可能会发生这种情况。