Исключение Bad_alloc при использовании new для struct c ++ - PullRequest
1 голос
/ 04 апреля 2010

Я пишу обработчик запросов, который выделяет большие объемы памяти и пытается найти подходящие документы. Всякий раз, когда я нахожу совпадение, я создаю структуру для хранения двух переменных, описывающих документ, и добавляю его в очередь с приоритетами. Поскольку невозможно узнать, сколько раз я это сделаю, я попытался создать свои структуры динамически, используя new. Когда я вытаскиваю структуру из очереди приоритетов, очередь (реализация очереди приоритетов STL) должна вызывать деструктор объекта. Мой структурный код не имеет деструктора, поэтому я предполагаю, что в этом случае вызывается деструктор по умолчанию.

Однако, когда я впервые пытаюсь создать структуру DOC, я получаю следующую ошибку:

Необработанное исключение в 0x7c812afb в QueryProcessor.exe: Microsoft C ++ исключение: std :: bad_alloc в ячейке памяти 0x0012f5dc ..

Я не понимаю, что происходит - я израсходовал столько памяти, что куча заполнена? Это не похоже на вероятность. И я даже не использовал этот указатель раньше.

Итак: во-первых, что я делаю, что вызывает ошибку, а во-вторых, будет ли следующий код работать более одного раза? Нужно ли иметь отдельный указатель для каждой созданной структуры, или я могу повторно использовать один и тот же временный указатель и предположить, что очередь будет хранить указатель на каждую структуру?

Вот мой код:

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.

Ответы [ 4 ]

4 голосов
/ 04 апреля 2010

Почему вы создаете следующую структуру в куче:

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

Сначала создается DOC в куче, затем сохраняется копия объекта в очереди, а затем происходит утечка динамически созданного DOC.

Следующее было бы достаточно и не протекает:

q.push(DOC(num, rank));
0 голосов
/ 04 апреля 2010

Об исключении: класс bad_alloc имеет функцию-член what(), которая возвращает const char * в строку, содержащую читаемое описание причины ошибки.

РЕДАКТИРОВАТЬ: Если вы планируете сохранить динамически размещенный объект, сохраните указатель, а не ссылку на объект.

0 голосов
/ 04 апреля 2010

У вас утечка памяти.Методы вставки для контейнеров STL хранят копию типа, который вы передаете, поэтому вам не нужно выделять документ в куче.

Вместо

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

Выполните либо

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

Или

doc = new DOC(...);
q.push(*doc);
delete doc;
doc = NULL;
0 голосов
/ 04 апреля 2010

std :: bad_alloc выбрасывается, когда у вас недостаточно памяти.

Вам нужно освободить указатель, который вы собираетесь выскочить, когда вы делаете q.pop (), иначе вы пропускаете. Если у вас много элементов, это может быть вашей проблемой.

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

Как уже упоминали другие, если вы объявляете свою очередь для хранения документов вместо документов, то вам не нужно управлять памятью самостоятельно, и контейнер сделает это за вас.

...