C ++标准模板库优先级队列抛出异常,消息“Invalid Heap”

时间:2009-01-23 22:15:44

标签: c++ heap priority-queue

使用STL priority_queue我尝试使用pop()时会收到错误“无效堆”。我可以将我的值推送到队列中,队列的top()是我期望和可访问的。 pop(),当它重新堆叠时,似乎有问题。

我存储指向队列中模板化类的指针。我有比较重载:

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行。

5 个答案:

答案 0 :(得分:3)

这可能是你的比较功能。要进行测试,请将其替换为仅比较指针的简单版本:

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

如果问题不再出现,则问题是您的比较功能无效。您的比较器必须定义"strict-weak ordering"。我不足以表明它没有,但我打赌就是这样。

答案 1 :(得分:3)

比较函数看起来很好,如果对象getDistanceFromSource()的值没有改变,而该对象在队列中。这确保了吗?或者是否有可能影响getDistanceFromSource()的对象,当它们在队列中或队列最初被填充时?

答案 2 :(得分:0)

你从哪里调用这个函数?

我的猜测是无效堆是一个指针,你从“this function caller”代码传入函数。或者当你从矢量中取出顶点时,你可能会走出界限。

我认为该功能没有任何问题。

请提供堆栈跟踪

答案 3 :(得分:0)

如果没有callstack,确定问题是什么有点困难,但是你要么没有正确分配Vertex<...>,要么从堆栈中释放Vertex<...>,要么没有初始化Vertex<...>*有效值。

答案 4 :(得分:0)

这一点让我害怕:

  

我动态声明一个数组   指针指针,这些是什么   被推,因为我认为   priority_queue按引用存储,所以   如果我只是把一个指针声明   循环进入队列,即指针   超出范围。这些指针   指向正确的顶点,并存在   整个功能。

目前还不清楚你是如何填充队列的。 您必须创建Vertex对象,它们必须保留在内存中,并在队列中的整个时间内返回相同的距离。

队列不通过引用存储,它存储副本 - 但在这种情况下,您输入的是指针,因此它复制指针,指针仍将指向您分配的原始对象。

我认为我们需要一个简短的完整示例才能获得更多。