странный дефект сегментации и анализ валгринда - PullRequest
0 голосов
/ 23 марта 2012

У меня был код для запуска компьютерного моделирования мембраны. Я добавил небольшую модификацию, которая вызвала самую странную ошибку сегментации. В моем коде я настроил карту:

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. на более поздней стадии кода есть примечание, что:

Условный переход или перемещение зависит от неинициализированных значений

  1. Есть также и другие сообщения от valgrind, на которых я сейчас не фокусируюсь. По крайней мере, некоторые из них связаны с этими двумя.

В строке, которая сравнивается с двойными значениями, которые были объявлены ранее (одно - это первое значение, сгенерированное в симуляции, а другое - элемент, который я хочу проверить, который определяется.

Итак, у меня два вопроса: 1. Об ошибке сегментации. в чем смысл этого вывода valgrind? Как это может быть, что установка значения карты недопустима.

  1. Об ошибке условного перехода. Как это может быть? Возможно ли, что valgrind неправильно интерпретирует позицию ошибки?

Спасибо за любую помощь

Edit:
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 (стандартный вывод);

как до, так и после указанной строки.

Ответы [ 2 ]

2 голосов
/ 23 марта 2012

Во-первых, жалоба valgrind о переходе на неинициализированное значение, вероятно, верна. Правильный код C ++ не генерирует это предупреждение. (обратите внимание, здесь я делаю предположение, что в valgrind загружены исключения по умолчанию, потому что может быть код стандартной библиотеки расположений, который предназначен для правильной работы независимо от того, было ли значение инициализировано чем-то вменяемым или нет, возможно, глупое предположение учитывая качество остальной части вашего вопроса) Большой ошибкой является то, что в вашей структуре нет конструктора, который бы инициализировал значения x, y, z. Значения базового типа, выделенные в куче, остаются неинициализированными и содержат случайный мусор памяти! Тем не менее, это вряд ли причина, по которой вы терпите крах.

Во-вторых, подумайте об этом, std :: map - это своего рода дерево. Предполагается, что от каждого узла оставлены дочерние элементы меньшего размера, а более крупные - правого. Поэтому, когда вы меняете что-то внутри, что влияет на сортировку, например, вы заходите в индекс и меняете x, y или z, то есть вы меняете ключ из-под std :: map, не зная об этом, узел остается на своем месте, что внезапно НЕПРАВИЛЬНО, потому что он нарушает основное предположение структуры данных! В этом случае вы должны удалить запись и вставить ее с новым индексом, который поместит ее в правильное место в наборе. Такая неудачная вещь случалась со мной несколько раз. Я до сих пор не знаю ДЕЙСТВИТЕЛЬНО элегантного способа сделать это, но, по крайней мере, здесь, возможная и вероятная причина.

Конечно, настоящая ошибка не в том коде, который вы разместили, и даже неясно, где и что и как сильно вы изменили, и отсутствие обратного следа в месте падения не помогает вообще.

1 голос
/ 12 сентября 2012

Никогда не забывай о восстановлении.

Сегодня со мной произошла очень похожая вещь.Странное, «случайное» поведение, вылетает в stl ... Это показало, что это была проблема сборки - что-то не было перестроено после изменения заголовка.

...