【问题标题】:Bad_alloc exception when using new for a struct c++将 new 用于 struct c++ 时出现 Bad_alloc 异常
【发布时间】:2010-04-04 17:35:08
【问题描述】:

我正在编写一个查询处理器,它分配大量内存并尝试查找匹配的文档。每当我找到匹配项时,我都会创建一个结构来保存描述文档的两个变量并将其添加到优先级队列中。由于无法知道我会这样做多少次,我尝试使用 new 动态创建我的结构。当我从优先级队列中弹出一个结构时,队列(STL 优先级队列实现)应该调用对象的析构函数。我的结构代码没有析构函数,所以我假设在这种情况下调用了默认析构函数。

但是,我第一次尝试创建 DOC 结构时,出现以下错误:

QueryProcessor.exe 中 0x7c812afb 处未处理的异常:Microsoft C++ 异常:内存位置 0x0012f5dc 处的 std::bad_alloc..

我不明白发生了什么 - 我是否用尽了太多内存以至于堆已满?似乎不太可能。而且好像我以前什至没有使用过那个指针。

所以:首先,我在做什么导致错误,其次,以下代码会多次工作吗?我是否需要为每个创建的结构创建一个单独的指针,或者我可以重复使用相同的临时指针并假设队列将保留一个指向每个结构的指针?

这是我的代码:

struct DOC{
    int docid;
    double rank;

    public:
        DOC()
        {
            docid = 0;
            rank = 0.0;
        }

        DOC(int num, double ranking)
        {
            docid = num;
            rank = ranking;

        }

        bool operator>( const DOC & d ) const {
           return rank > d.rank;
        }

        bool operator<( const DOC & d ) const {
           return rank < d.rank;
        }
};


//a lot of processing goes on here

        priority_queue<DOC, std::vector<DOC>, std::greater<DOC>> q;

//when a matching document is found, I do this:

rank = calculateRanking(table, num);

    //if the heap is not full, create a DOC struct with the docid and rank and add it to the heap
    if(q.size() < 20)
    {
        doc = new DOC(num, rank);
        q.push(*doc);
        doc = NULL;
    }

    //if the heap is full, but the new rank is greater than the 
    //smallest element in the min heap, remove the current smallest element
    //and add the new one to the heap
    else if(rank > q.top().rank)
    {
        q.pop();

        cout << "pushing doc on to queue" << endl;
        doc = new DOC(num, rank);
        q.push(*doc);
    }

非常感谢你,bsg。

【问题讨论】:

  • 不确定是否重要,但是当重载&lt;&gt; 时,我也会重载==!=

标签: c++ stl priority-queue bad-alloc


【解决方案1】:

为什么要在堆上创建如下结构:

doc = new DOC(num, rank);
q.push(*doc);

这首先在堆上创建一个DOC,然后将该对象的副本存储在队列中,随后泄漏动态创建的DOC

以下内容就足够了,不会泄漏:

q.push(DOC(num, rank));

【讨论】:

    【解决方案2】:

    关于异常:类bad_alloc 有一个成员函数what(),它返回一个const char * 到一个包含错误原因的可读描述的字符串。

    编辑:如果您正在考虑存储动态分配的对象,请存储指针而不是对该对象的引用。

    【讨论】:

      【解决方案3】:

      std::bad_alloc 内存不足时抛出。

      当你执行 q.pop() 时,你需要释放你即将弹出的指针,否则你会泄漏。如果您有很多元素,这可能是您的问题。

      Doc *p = q.front();
      delete p;
      q.pop();
      

      正如其他人所提到的,如果您声明队列来保存 Doc 而不是 Doc*,那么您不必自己管理内存,容器会为您完成。

      【讨论】:

      • 我知道。但是我该如何解决呢?
      • 我的队列确实保存了 DOC,而不是 DOC*。感谢您提供有关弹出的提示 - 如果我的队列包含 DOC 而不是 DOC*,它是否仍然适用?
      • 进入底层代码发现错误出现在这里: // 为_Ty类型的_Count个元素分配存储 return ((_Ty _FARQ *)::operator new(_Count * sizeof (_Ty) )); 00421B08 mov eax,dword ptr [_Count] 00421B0B shl eax,4 00421B0E push eax 00421B0F call operator new (4117DFh) 00421B14 add esp,4 typename A::template rebind::other::pointer #define _REFERENCE_X(T, A) \ typename A::template rebind::other::reference 看起来它在为队列元素分配内存时遇到了问题。知道为什么会这样吗?
      【解决方案4】:

      您有内存泄漏。 STL 容器的插入方法会存储您传入的类型的副本,因此您无需在堆上分配 doc。

      代替

      doc = new DOC(...)
      q.push(*doc);
      doc = NULL;
      

      做任何一个

      doc(...);
      q.push(doc);
      

      或者

      doc = new DOC(...);
      q.push(*doc);
      delete doc;
      doc = NULL;
      

      【讨论】:

      • 我听从了您的建议,并在方法的开头创建了一个 DOC(静态分配),然后执行以下操作: if(q.size()
      • @bsg,如果没有像调用堆栈这样的更多信息,或者不知道你在做什么,调试它会非常困难。
      猜你喜欢
      • 2012-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 1970-01-01
      • 1970-01-01
      • 2021-11-12
      • 1970-01-01
      相关资源
      最近更新 更多