我使用两个名为IndexedHeap和HeapEntry的类实现了一个堆。我有一些损坏的内存访问导致段错误,我相信我知道在哪里/为什么,但我不知道如何解决它。以下是我到目前为止设计这些类的方法:
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)
{}
};
堆及其条目都需要相互引用。如您所见,我决定在HeapEntry中使用指向IndexedHeap的原始指针。这是我认为我错了的地方,但我不确定。
在整个程序执行过程中,新堆条目将作为一个堆的一部分创建。条目也会从此堆中删除并销毁。也许当一个堆条目被销毁时,它指向的堆就会被破坏。这可以解释我的内存问题,因为下次堆条目尝试访问其堆时,它会访问已释放的内存。
不幸的是我不相信这一点。我还没有为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);
}
}
答案 0 :(得分:1)
那么,首先,为什么你不使用STL的优先级队列,或者使用多重映射作为优先级队列?它比写自己的解决方案更好。
接下来,代码结构:std::vector<HeapEntry*> heap;
因泄漏内存而臭名昭着,人们没有删除指向的内存,而当人们试图删除指向的内存并导致删除错误时会导致严重的内存错误。
"IndexedHeap* myHeap;"
很可能不是你的问题。如果有人删除了那些对象,那么引用你不拥有的东西可能是一个问题,但是那时你可能已经停止使用这些条目了。顺便说一句,因为它是一个引用,你应该考虑将它作为一个引用(然后在ctr期间绑定并且永远不会改变) - 但无论如何都要改变代码的安全性。你可能不相信,指针的dtr对目标没有任何作用。
你能跑valgrind吗?它很快就解决了这样的问题。否则:
尝试不删除任何条目,并查看是否可以解决您的错误,如果是这样的话。
您还可以尝试通过打印或全局设置/地图对象跟踪新建和删除的指针。找到这些东西很方便。