2012-01-30 2 views
0

У меня есть простой двусвязного пример списка, который я работаю, но по какой-то причине, я получаю ошибку: pointer being freed was not allocated при попытке удалитьНе удается удалить в C++

Вот код snipet из вставка в конец списка метода

template <class T> 
void List<T>::insertAtEnd(T *o) 
{ 
    node *newNode = new node; 
    newNode->o = o; 
    newNode->next = NULL; 
    newNode->prev = last; 
    if(last != NULL) 
     last->next = newNode; 
    last = newNode; 
    if(first == NULL) 
     first = newNode; 
    delete(newNode);   // This delete call will usually be in another method 
}        // It is just here right now for testing 

Этот класс имеет два экземпляра поля, указатель на начало списка и указатель на конец, первый и последний respecitvely. Каждый узел является структурой следующим образом:

struct node { 
    node *next; 
    node *prev; 
    T  *o; 
}; 

До сих пор я тестировался только с вставкой 1 узел, но я всегда получаю ту же ошибку. Однако, если я прокомментирую строки

if(first == NULL) 
    first = newNode; 

это работает. Помоги пожалуйста? Спасибо

EDIT: Первый и последний старт как NULL.

+0

Где произносится 'first'? – prelic

+0

Происходит ли код, который вы отправили здесь? Или вы говорите о каком-то другом коде, который мы не видим? –

+0

Его глобальная переменная, которую я устанавливаю равной нулю в конструкторе. То же самое касается последних – Nosrettap

ответ

2

У вас, к сожалению, не указан весь код. Вы опустили раздел, содержащий вашу ошибку, поэтому я должен рассказать о конкретной причине.

Ошибка, которую вы видите, указывает, что delete вызывается по адресу, который не был получен через new. Вероятно, это означает, что вы непреднамеренно выполняете присвоение значения вместо назначения указателя , а затем пытаетесь освободить скопированную (распределенную стекю) переменную. Один конкретный способ это может произойти, если вы попытаетесь сделать delete mynode->o, так как o может быть адресом переменной стека.

Двойная проверка, что каждый тип, который должен быть node*, является node*, а не node или node**. Компиляция кода с помощью -Wall -Wextra может привести к дополнительным предупреждениям и должна стать первым шагом отладки, если не общая практика.

Если ваши типы и назначения правильны, вы можете использовать библиотеку C++ или компилятор, который не дает вам конкретных двухсторонних сообщений; это расширит объем ошибки, которую вы видите, чтобы включить освобождение одной и той же памяти дважды. Попробуйте распечатать адрес непосредственно перед его освобождением (или с помощью отладчика с тем же эффектом). Когда вы видите один и тот же адрес, выходите дважды, вот и все.

Это может быть очевидно, но вы не можете позвонить по телефону delete и работать правильно. first и last укажут на освобожденную память. Почувствовав, что нужно было сказать, на всякий случай.

+0

Думаю, вы, возможно, решили это. Когда вы говорите, что я не могу указать указатель на освобожденную память, значит ли это, что я не могу указать, чтобы он указывал там даже на секунду? Даже если я не использую этот указатель? Если да, должен ли я сначала установить указатель в NULL перед удалением? Извините, я новичок в C++ – Nosrettap

+0

@Nosrettap Нет, он может указывать на освобожденную память, если вы ее не используете, но это рецепт катастрофы, чтобы оставить ее таким образом. При вызове 'delete', где у вас есть,' first' и 'last' оба будут указывать на освобожденную память после одного вызова. – Borealid

+0

Поскольку вышеописанный метод работает, если я устанавливаю сначала равным NULL прямо перед удалением – Nosrettap

1

Возможно, вы используете safe_ptr<T> для first и/или last? Затем вам нужно сделать отличное от T* при сравнении с NULL или 0. Но я все еще не вижу ошибки.

Более вероятно, что деструктор списка выполняет второе удаление на узле.

Смежные вопросы