Я реализовал кучу, используя два класса под названием IndexedHeap и HeapEntry. У меня есть поврежденный доступ к памяти, вызывающий segfaults, и я считаю, что знаю, где и почему, но я не уверен, как это исправить. Вот как я разработал классы до сих пор:Стратегия управления памятью с двумя путями в двух направлениях
class IndexedHeap
{
private:
std::vector<HeapEntry*> heap; // the entries held by this heap
public:
...
};
class HeapEntry
{
private:
int index;
size_t priority;
unsigned long long key;
IndexedHeap* myHeap; // reference to heap where this entry resides
public:
HeapEntry(unsigned long long key, size_t priority, IndexedHeap* myHeap)
: key(key), priority(priority), index(-1), myHeap(myHeap)
{}
};
Как куча, так и ее записи должны ссылаться друг на друга. Как вы можете видеть, я решил использовать необработанный указатель на IndexedHeap в HeapEntry. Здесь я думаю, что поступил неправильно, но я не уверен.
В ходе выполнения программы новые записи кучи создаются как часть одной кучей. Записи также удаляются из этой кучи и уничтожаются. Возможно, когда одна запись кучи будет уничтожена, куча, на которую указывает она, будет повреждена. Это объясняет мои проблемы с памятью, поскольку в следующий раз, когда запись кучи пытается получить доступ к своей куче, она обращается к освобожденной памяти.
К сожалению, я не уверен в этом. Я не реализовал деструктор для HeapEntry. Деструктор по умолчанию просто вызывает деструкторы для всех переменных экземпляра класса? Так не будет ли указатель на myHeap уничтожен, а сам кучный объект сохранится?
Итак, каков правильный способ создания такого рода отношений, и могут ли мои проблемы с памятью объясняться из кода, который я опубликовал? Спасибо, и, пожалуйста, дайте мне знать, если вы хотите увидеть больше кода или более подробную информацию.
код, который создает и уничтожает записи в куче:
HeapEntry* IndexedHeap::insert(unsigned long long key)
{
HeapEntry* entry = new HeapEntry(key, 1, this);
heap.push_back(entry);
int index = heapifyUp(heap.size() - 1);
heap[index]->setIndex(index);
return entry;
}
void IndexedHeap::deleteAtIndex(int pos)
{
if (pos >= 0 && pos < heap.size())
{
// Copy heap.back() into the position of target, thus overwriting it
*heap[pos] = *heap.back();
// Fix the index field for the just copied element
heap[pos]->setIndex(pos);
// We've removed the target by overwriting it with heap.back()
// Now get rid the extra copy of heap.back()
// Release the mem, then pop back to get rid of the pointer
delete heap.back();
heap.pop_back();
// Heapify from the position we just messed with
// use heapifyDown because back() always has a lower priority than the element we are removing
heapifyDown(pos);
}
}
Как распределяется HeapEntry и как он должен освобождаться? Как вы убедитесь, что у кого-то нет указателя на уже освобожденный HeapEntry? Использование простого старого указателя в классе STL-контейнера является верным билетом для повреждения памяти, если STL-контейнер участвует в освобождении вашего указателя. Вы должны пойти и прочитать о умных указателях. –
Ну, почему вы не используете приоритетную очередь из STL или используете мультимап в качестве очереди приоритетов? Это лучшее решение, чем писать свои собственные. – RichardPlunkett
Я не слишком хорошо знаком с умными указателями, поэтому я обязательно прочитаю их и попытаюсь посмотреть, где они могут помочь.Теперь я также отредактирую вопрос, чтобы включить код, который создает и уничтожает записи кучи. – yan