从stl_list.h:731引发的分段错误

时间:2014-03-10 04:06:30

标签: c++ opengl

我的代码有一个非常奇怪的分段错误。实际上,当我运行我的可执行文件时,它会中止。当我用gdb运行它时,它也会中止。但是当我用valgrind运行它时,它会成功终止并给我正确的结果。

这是介绍。现在这里是我的算法的描述。我想要做的是在给定某个阈值 r 的情况下提取看起来类似于另一个网格的网格的子表面。我的算法的关键思想是在网格的每个点上循环(比方说, p )。如果我发现参考网格的一个点包含在中心 p 和radius r 的球体中,我什么都不做,我会转到下一个点。否则,我删除点和网格的每个元素,包括它(这意味着,点所属的网格的边和三角形)。

现在我跳到我的课程的简短描述。我有四个类来表示网格的元素:

  • 顶点。这个类包括两个属性(我没有提到getter和setter):一个位置和一个列表belongsTo,它包含指向顶点所属的所有边的指针。
  • 边缘。这个类包括三个属性:分隔边的两个顶点,以及一个名为belongsTo的列表,wichi包含指向边所属的所有三角形的指针。
  • 三角。这个类包括三个属性:三角形分隔三角形和一个法线向量(我提到过,但这里并不重要:我只用它来渲染使用OpenGL的三角形)。

最后:

  • 网。这个类包括一个Vertex objets的矢量v,一个Edge对象的矢量e,最后是一个三角形的矢量t。

现在这是我的功能原型:

class Mesh {

    ...

    void extractIdenticalSubsurfaces(Mesh *a, double threshold);

}

正如您可能已经猜到的,此函数需要考虑两个参数:参考网格和阈值(实际上是我构建的球体的半径,以确定是否必须从网格中删除点)。一切都清楚了吗?

我的算法描述:我在网格的每个点上循环(实际上在v的每个点上)。对于每个点,我构建一个以此为中心的半径“阈值”球体,并验证它在该球体中有一个点。如果我找到一点,我什么都不做。否则,我从v。

中删除它

但在此之前,我有一些操作要做。

实际上,我必须在该点所属的每个边上循环(使用列表'belongsTo')然后在该点所属的每个三角形上循环(再次使用列表'belongsTo')。

对于这些三角形中的每一个,我在界定它的三条边上循环,我从该三角形所属的边列表中删除三角形的地址(因为我想删除这个三角形,所以我必须预料到)

一旦完成,我对循环的当前边缘做同样的事情:我从与边缘的两个顶点相关联的'belongsTo'列表中删除边的地址。

但我还必须从矢量e和t中删除被抑制的边和三角形!

看起来似乎并不那么容易理解(我认为如果你面前有一张纸,如果你画一个网格并考虑一个你要压制的点,那会更好)但我很确定这个算法的精确性:实际上,当我用valgrind运行我的程序时,它会在我的屏幕上显示好的子网格。

但问题是,如果我不使用valgrind,它就会失败。

这是gdb显示的错误消息:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000406f3a in std::list<Triangle*, std::allocator<Triangle*> >::begin (this=0x39) at /usr/include/c++/4.6/bits/stl_list.h:731
731       { return iterator(this->_M_impl._M_node._M_next); }

回溯:

(gdb) bt
#0  0x0000000000406f3a in std::list<Triangle*, std::allocator<Triangle*> >::begin (this=0x39) at /usr/include/c++/4.6/bits/stl_list.h:731
#1  0x0000000000406e37 in std::list<Triangle*, std::allocator<Triangle*> >::remove (this=0x39, __value=@0x7fffffffc860) at /usr/include/c++/4.6/bits/list.tcc:242
#2  0x00000000004062a1 in Edge::deleteTriangle (this=0x21, t=0xcf4ed0) at elements.cpp:109
#3  0x0000000000408aa4 in Mesh::extractIdenticalSubsurfaces (this=0xc14b10, a=0xc0f900, threshold=0) at mesh.cpp:174
#4  0x0000000000404687 in Scene::extractIdenticalSurfaces (this=0xbad8c0, threshold=0) at scene.cpp:36
#5  0x00000000004051c6 in Viewer::keyPressEvent (this=0x7fffffffde80, e=0x7fffffffd020) at viewer.cpp:104
...

正如您所看到的,获取错误在这里是合乎逻辑的,因为系统似乎试图在'this'地址为0x21的对象上应用'deleteTriangle'方法。但我想知道的是,它究竟是怎么样的0x21。我试图显示指向所有三角形和边缘对象中包含的边和顶点的指针的地址,它们似乎是正确的(毕竟我可以使用OpenGL显示网格的所有元素,所以...) 。但是在某个时刻,这个0x21进来了,我肯定不知道为什么。

这是我的代码:

void Mesh::extractIdenticalSubsurfaces (Mesh *a, double threshold) {
  vector<Vertex *>::iterator it1 = v.begin() ;
  while (it1 != v.end()) {
    if (a->emptySphere((*it1), threshold)) {
      list<Edge *> edgesToDelete = list<Edge *>();
      list<Triangle *> trianglesToDelete = list<Triangle *>();
      for (list<Edge *>::iterator it2 = (*it1)->getIteratorBegin() ; it2 != (*it1)->getIteratorEnd() ; it2++) {
        for (list<Triangle *>::iterator it3 = (*it2)->getIteratorBegin() ; it3 != (*it2)->getIteratorEnd() ; it3++) {
          Triangle *argT = (*it3);
          (*it3)->getFirstEdge()->deleteTriangle(argT);
          (*it3)->getSecondEdge()->deleteTriangle(argT);
          (*it3)->getThirdEdge()->deleteTriangle(argT);
          trianglesToDelete.push_back(argT);
        }
        Edge *argE = (*it2);
        (*it2)->getFirstVertex()->deleteEdge(argE);
        (*it2)->getSecondVertex()->deleteEdge(argE);
        edgesToDelete.push_back(argE);
      }
      edgesToDelete.unique();
      trianglesToDelete.unique();
      vector<Edge *>::iterator it4 = e.begin();
      while (it4 != e.end()) {
        bool isEqual = false;
        for (list<Edge *>::iterator it5 = edgesToDelete.begin() ; it5 != edgesToDelete.end() ; it5++) {
          if ((*it4) == (*it5)) {
            isEqual = true;
            edgesToDelete.erase(it5);
            break;
          }
        }
        if (isEqual) {
          e.erase(it4);
        } else {
          it4++;
        }
      }
      vector<Triangle *>::iterator it6 = t.begin();
      while (it6 != t.end()) {
        bool isEqual = false;
        for (list<Triangle *>::iterator it7 = trianglesToDelete.begin() ; it7 != trianglesToDelete.end() ; it7++) {
          if ((*it6) == (*it7)) {
            isEqual = true;
            trianglesToDelete.erase(it7);
            break;
          }
        }
        if (isEqual) {
          t.erase(it6);
        } else {
          it6++;
        }   
      }
      v.erase(it1);
    } else {
      it1++;
    }
  }
}

(好吧,有时不太漂亮,我同意,但这不是我的问题的主题(一见钟情))

那么,你知道我为什么会收到这个错误吗?

0 个答案:

没有答案