使用Boost :: Heap句柄的Seg Fault

时间:2013-02-22 19:47:06

标签: c++ boost binomial-heap

这里的新(坏)C ++程序员(所以请不要介意所有非本质上的错误/简化以便于阅读):

使用Boost :: heap句柄时遇到了一致的问题。我通常要么出现故障,要么进入一个没有意义的状态(最终导致seg故障)。基本上我所拥有的是地图矢量。我将整数(索引)映射到EdgeStructs的句柄。我首先用EdgeStructs填充堆。堆是在EdgeStruct.value上键入的。

typedef boost::heap::binomial_heap<EdgeStruct*>::handle_type handle_t;
std::vector<std::map<int,handle_t> > indexToIndex;
boost::heap::binomial_heap<EdgeStruct*> heap;

void class::populateStructures(void) {
  while (populating data structures) {
    ...
    EdgeStruct* q = new EdgeStruct;
    q->value = -error;
    q->index1 = index1;
    q->index2 = index2;
    q->alive = true;
    handle_t handyq = heap.push(q);
    indexToIndex[index1][index2] = handyq;
    indexToIndex[index2][index1] = handyq;
  }
}

然后我遍历堆,在我继续的时候弹出结构。

void class::iterateOverHeap(void) {
  populateStructures();
  while (!heap.empty()) {
    this->bestEdgeStruct = heap.top();
    if (this->bestEdgeStruct->alive)
      destroyIndices(this->bestEdgeStruct->index1, this->bestEdgeStruct->index2);
    heap.pop();
  }
}

在destroyIndi​​ces()中,我在一些其他函数中更新堆中这些结构的值:

void class::someOtherFunction(void) {
  map<int,handle_t>::iterator iter;
  ...
    for (iterating using iter) {
      (*(iter->second))->value = error;
      heap.update(iter->second);
    }
}

我还在indexToIndex中的某些点处的新旧映射中向堆中添加了新结构以及这些结构的新句柄。还没有真正的问题。但是我也希望在destroyIndi​​ces()期间擦除一些完全从堆中变为无效的结构。我做的是通过迭代某些indexToIndex映射,从这些映射中删除它们的句柄,然后将句柄指向的结构设置为dead来找到某些结构,以便不调用iterateOverHeap()中的destroyIndi​​ces(),并且它而是被弹出并被遗忘。我也在destroyIndi​​ces()中调用了这个函数:

void class::killStructInMapsAndHeap(int index, int otherIndex) {
  map<int,handle_t>::iterator it;
  map<int,handle_t>::iterator otherIt;

  it = indexToIndex[index].begin();
  while (it != indexToIndex[index].end()) {
    otherIt = indexToIndex[it->first].find(index);
    handle_t handle = it->second;  

    if (*handle != bestEdgeStruct) {
      cout << "Seg faults can happen here\n";
      (*handle)->alive = false;
      cout << "Or here\n";
      heap.update(handle);
    }

    if (otherIt != indexToIndex[it->first].end()) {
        indexToIndex[it->first].erase(otherIt);
    } else {
        cout << "Problem!"
    }   

    indexToIndex[index].erase(it++);           
  }
}

每次在couts之后,我几乎都会出错。我尝试了其他的东西(比如直接擦除句柄而不是等待从堆中弹出它),但是那些问题也存在同样的问题。

Based on the documentation here,似乎将句柄存储在向量中然后迭代它们并更新相应的结构应该没有问题,即使我已经更新或添加了其他结构到堆。但是在iterateOverHeap()中有一些(有些)随机数的循环之后,访问句柄指向的结构或更新堆中的句柄会导致seg错误。

这是否意味着我无法在向量中存储句柄,因为一段时间后它们变得无效?或者是否有一些错误,即使在以不同方式重写其中一些函数后,会导致我的句柄无效?或者当我运行populateStructures()时,我没有正确获取EdgeStruct句柄?

我“解决”这种方法的一种方法是永远不更新堆,而是每次我对数据结构进行更改时清除它并重新填充它。但随着我的数据量增加(100,000多个元素),这可能变得非常缓慢,因此这是不切实际的。感谢您的帮助(让我知道如何更好地解决这个问题)!

0 个答案:

没有答案