2009-01-23 10 views
3

使用STL的priority_queue只要我嘗試使用pop(),就會收到錯誤「invalid heap」。我可以將我的值推入隊列,隊列的top()是我期望和可訪問的。 pop(),當它重新堆積時,似乎有問題。C++標準模板庫優先級隊列拋出帶有消息「Invalid Heap」的異常

我正在存儲指向隊列中模板類的指針。我有重載的對比:

template <class type> 
class vertexPriorityCompare 
{ 
public: 
    bool operator()(Vertex<type>* leftVertex, Vertex<type>* rightVertex) const 
    { 
     if(leftVertex->getDistanceFromSource() < 0 && rightVertex->getDistanceFromSource() < 0) 
     { 
     return false; 
     } 
     else if(leftVertex->getDistanceFromSource() < 0) 
     { 
     return true; 
     } 
     else if(rightVertex->getDistanceFromSource() < 0) 
     { 
     return false; 
     } 
     else 
     { 
     return leftVertex->getDistanceFromSource() > rightVertex->getDistanceFromSource(); 
     } 
    } 
}; 

priority_queue是一類的私有成員:

priority_queue< Vertex<type>*, vector< Vertex<type>* >, vertexPriorityCompare<type> > Q; 

在它時尚的超負荷工作,因爲負的距離被認爲是無窮大,總是大於不管怎麼說;爲了表示無窮大,距離被初始化爲-1。隊列需要保持最小值,但非負值。

我解引用重載中的指針,是我在那裏允許的嗎?而且,是否還有另一個運營商需要超載?

我會附上代碼,但看起來如果我這樣做,它會嚇跑人們。要求看更多,我會附加到另一條消息。

我動態地聲明瞭一個指向指針的數組,這些是被推入的東西,因爲我認爲priority_queue是通過引用存儲的,所以如果我只是把循環中聲明的指針放入隊列中,那麼這個指針會超出範圍。這些指針指向正確的Vertex<type>,並存在於整個函數中。

Visual Studio 2008中調試帶我到「stdthrow.cpp」線路24

+0

請格式化您的代碼 – cbrulak 2009-01-23 22:17:15

+0

Visual Studio調試器也應該爲您提供一個調用堆棧。這可能也有幫助。 – MSN 2009-01-23 22:24:37

回答

0

你在哪裏調用這個函數?

我的猜測是無效堆是一個指針,你從「this function caller's」代碼傳入函數。或者,當你從矢量中取出頂點時,你可能會走出界限。

我沒有看到任何錯誤的功能。

請提供堆棧跟蹤

0

沒有調用堆棧,這將是一個有點難以確定的問題是什麼,但你可能是沒有正確地分配Vertex<...>,試圖從堆棧中釋放Vertex<...>,或不初始化Vertex<...>*爲有效值。

3

這可能是你的比較功能。爲了測試,用一個簡單的版本,只是比較指針替換:

bool operator()(...) 
{ 
    return leftVertex<rightVertex; 
} 

如果問題不再出現,那麼問題是你比較函數是無效的。您的比較器必須定義一個"strict-weak ordering"。我沒有足夠的人來證明它沒有,但我敢打賭就是這樣。

+1

+1「嚴格弱排序」的一部分表示,如果Compare(x,y)爲true,則Compare(y,x)*必須爲* false。如果兩個距離值均爲-1,則此功能不處理該情況。 – 2009-01-23 23:49:08

3

比較函數看起來不錯,如果對象getDistanceFromSource()的值不會更改,而該對象在隊列中。這是保證嗎?或者是否可能對這些對象進行更改,影響getDistanceFromSource(),而這些更改是在隊列中還是隊列初始填充期間進行的?

0

這一點讓我害怕:

我動態申報 指針數組的指針,這是什麼意思 得到推,因爲我引用假設 priority_queue店,所以 如果我只是把一個指針在 中聲明循環進入隊列,該指針 超出範圍。這些指針 指向適當的頂點,並在整個函數中存在 。

你不清楚你是如何填充隊列的。 您必須創建頂點對象,並且它們必須保留在內存中,並且在隊列中的整個時間內返回相同的距離。

隊列不通過引用存儲,它存儲副本 - 但在這種情況下,您所放入的是指針,因此它會複製指針,該指針仍將指向您分配的原始對象。

我想我們需要一個簡短的完整例子才能得到更多。