开发者

Bad_alloc exception when using new for a struct c++

I am writing a query processor which allocates large amounts of memory and tries to find matching documents. Whenever I find a match, I create a structure to hold two variables describing the document and add it to a priority queue. Since there is no way of knowing how many times I will do this, I tried creating my structs dynamically using new. When I pop a struct off the priority queue, the queue (STL priority queue implementation) is supposed to call the object's destructor. My struct code has no destructor, so I assume a default destructor is called in that case.

However, the very first time that I try to create a DOC struct, I get the following error:

Unhandled exception at 0x7c812afb in QueryProcessor.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0012f5dc..

I don't understand what's happening - have I used up so much memory that the heap is full? It doesn't seem likely. And it's not as if I've even used that pointer before.

So: first of all, what am I doing that's causing the error, and secondly, will the following code work more than once? Do I need to have a separate pointer for each struct created, or can I re-use the same temporary pointer and assume that the queue will keep a pointer to each struct?

Here is my code:

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 = ca开发者_JS百科lculateRanking(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);
    }

Thank you very much, bsg.


Why are you creating the structure in the following on the heap:

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

This first creates a DOC on the heap, then stores a copy of the object in the queue and subsequently leaks the dynamically created DOC.

The following would be sufficient and doesn't leak:

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


About the exception: The class bad_alloc has a member function what() which returns a const char * to a string containing a readable description of the cause of the error.

EDIT: If you are considering storing a dynamically allocated object, store the pointer and not a reference to the object.


std::bad_alloc is thrown when you are out of memory.

You need to free the pointer you are about to pop when you do the q.pop(), else you are leaking. If you have a LOT of elements this could be your problem.

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

As others have mentioned, if you declare your queue to hold Doc's instead of Doc*'s, then you don't have to manage memory yourself and the container will do it for you.


You have a memory leak. The insertion methods for STL containers store a copy of the type you pass in so you don't need to allocate doc on the heap.

Instead of

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

Do either

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

Or

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜