奇怪的分段错误和valgrind分析

时间:2012-03-22 22:22:35

标签: c++ map segmentation-fault valgrind

我有一个代码来运行膜的计算机模拟。我添加了一些小修改,导致最奇怪的分段错误。在我的代码中,我设置了一张地图:

struct index{
  int x;
  int y;
  int z;
  bool operator<(const index &b) const {
    bool out = true;
    if (x == b.x){
      if (y == b.y){  
    out = z < b.z;
  }else out = y < b.y;
    }else out = x < b.x;
    return out;
  }
};
map<index,set<std::pair<int, int> > > tBoxes;

当我

时发生分段错误
if (tBoxes.find(t) == tBoxes.end()) continue;

所以,当我通过valgrind运行代码时,我看到: 1.当我第一次为地图指定值时,我有这个:

==26196== 6,568 (96 direct, 6,472 indirect) bytes in 1 blocks are definitely lost in loss record 86 of 145
==26196==    at 0x4A0666E: operator new(unsigned long) (vg_replace_malloc.c:220)
==26196==    by 0x4333C6: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::allocate(unsigned long, void const*) (new_allocator.h:88)
==26196==    by 0x4333EB: std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_get_node() (stl_tree.h:358)
==26196==    by 0x433407: std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_create_node(std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > const&) (stl_tree.h:367)
==26196==    by 0x434474: std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > const&) (stl_tree.h:819)
==26196==    by 0x434919: std::_Rb_tree<membrane::index, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > >, std::_Select1st<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::insert_unique(std::_Rb_tree_iterator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > const&) (stl_tree.h:962)
==26196==    by 0x434B52: std::map<membrane::index, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::insert(std::_Rb_tree_iterator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > >, std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > const&) (stl_map.h:420)
==26196==    by 0x434C3B: std::map<membrane::index, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > >, std::less<membrane::index>, std::allocator<std::pair<membrane::index const, std::set<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > > > > >::operator[](membrane::index const&) (stl_map.h:348)
  1. 在代码的某个后期阶段,请注意:
  2.   

    条件跳转或移动取决于未初始化的值

    1. 还有valgrind的其他消息,我目前没有关注。至少其中一些与这两者有关。
    2. 在一行上比较之前声明的double值(一个是模拟中生成的第一个值,另一个是我想检查的元素,这是确定的。

      所以我有两个问题: 1.关于分段错误。这个valgrind输出的含义是什么?如何设置地图值无效。

      1. 关于条件跳转错误。怎么会这样? valgrind是否有可能错误地解释错误位置?
      2. 感谢您的帮助

        修改
        1. t是一个合法定义的索引元素。 我用了一个循环:

        index t;
        for (int i = mini; i <= maxi; i++){ //mini and maxi are previously defined
          if (i < 0) t.x = i + P.boxNum; //P.boxNum is an integer, defined when I start the code
          else if (i >= P.boxNum) t.x  = i - P.boxNum;
          else t.x = i;
          for (int j = minj; j <= maxj; j++){//maxj and minj are previously defined
            if (j < 0) t.y = j + P.boxNum;
            else if (j >= P.boxNum) t.y =j - P. boxNum;
            else t.y = j;
            for(int k = mink; k <= maxk; k++){//mink and maxk are previously defined
              if (k < 0) t.z = k + P.zBoxNum;
              else if (k >= P.boxNum) t.z =k - P. zBoxNum;
              else t.z = k;
              if (tBoxes.find(t) == eBoxes.end()) continue;
              //now I access tBoxes[t], this should be ok since if tBoxes[t] does not exist the loop should skip to the next value of k
            }
          }
        }
        
        1. 我使用以下方法找到了分段错误的确切位置:

          printf(“%i,%i,%i \ n”,t.x,t.y,t.z); fflush(stdout中);

        2. 在提到的行之前和之后。

2 个答案:

答案 0 :(得分:2)

首先,valgrind关于跳转未初始化值的抱怨可能是正确的。正确的C ++代码不会生成此警告。 (注意,我在这里做了一个假设,你在valgrind中加载了默认排除项,因为可能存在标准库代码的位置,这些代码被设计为正确地工作,无论该值是否已被初始化为理想的东西,可能是一个愚蠢的假设考虑你问题其余部分的质量)一个很大的错误就是你的结构中没有构造函数来初始化x,y,z值。在堆上分配的基本类型的值仍然未初始化,并将包含随机内存垃圾!但是,这不太可能是你崩溃的原因。

第二件事,想一想,std :: map是一种树。它假设从每个节点,留下较小的子节点,较大的子节点是正确的。因此,每当您更改影响排序的内容时,例如你进入索引并改变x,y或z,所以说你从std :: map下面改变了密钥,在没有它知道的情况下,节点停留在它的位置,这是突然错误的,因为它违反了基本的假设的数据结构!在这种情况下,您需要做的是删除条目并将其重新放入新索引,该索引将其置于集合中的正确位置。这种不幸的事情发生在我身上好几次。我仍然不知道一种非常优雅的方式来做到这一点,但至少,在这里,可能和可能的原因。

当然,实际的错误并不在你发布的代码中,而且甚至不清楚你改变的地点,内容和数量,以及没有对崩溃位置进行回溯根本没有帮助。

答案 1 :(得分:1)

永远不要忘记重建。

今天发生了很多同样的事情。奇怪的,“随机”的行为,在stl中崩溃......它显示它是一个构建问题 - 在更改标题后没有重建。