присвоение значения из вектора (из общего указателя) в общий указатель вызывает ошибку сегментации c ++ - PullRequest
1 голос
/ 17 августа 2011

В моем коде у меня есть vector <vector <vector <vector <std::tr1::shared_ptr<foo> > > > > с именем foosBoxes.Вложенный вектор играет роль имитации положения физических блоков.У меня также есть цикл while, который вызывает ошибку сегментации:

vector<std::tr1::shared_ptr<foo> >::iterator fooit = foosBoxes[x][y][z].begin(); //x,y,z are valid integer
std::tr1::shared_ptr<foo> aFoo;
while (fooit != foosBoxes[x][y][z].end()){
  aFoo = *fooit; //this cause segmentation fault
  fooit++;
  //some stuff which does not have an effect on fooit;
}

Я попробовал кое-что:
1. Я пытался использовать aFoo = *fooit++, но это не сработало.
2. Ошибка сегментации возникает примерно после нескольких тысячных циклов, которые прошли нормально.
3. Я попытался оценить проблему, и valgrind прошел через шаг.
4. В цикле, который выдает ошибку, я напечаталсчетчик до и после предполагаемой линии.когда перед строкой я получаю 8 отпечатков (размер вектора), а когда после меня получаю 7 отпечатков.

Как я могу это выяснить?

Обновление:
Я добавил цикл для запуска до основного цикла:

int kkk = 1214
int c = 0;
while (c < foosBoxes[x][y][z].end()){
   aFoo = foosBoxes[x][y][z][c++];
   printf("%i\t, kkk);
   fflush(stdout);
}

, который дает те же результаты.

Обновление:
в соответствии с GDB:

Запрограммировать полученный сигнал SIGSEGV, Ошибка сегментации.0x000000000043e400 в повороте (kkk = 1214) в /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/tr1/boost_shared_ptr.h: 153 153 dispose ();

Я думаю, что подходящей функцией в boost_shared_ptr.h является

void
  release() // nothrow                                                                                                                      
  {
    if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1)
      {
        dispose(); //this is line 153
#ifdef __GTHREADS
        _GLIBCXX_READ_MEM_BARRIER;
        _GLIBCXX_WRITE_MEM_BARRIER;
#endif
        if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
          destroy();
      }
  }

dispose(), определенная в другом месте файла:

  // dispose() is called when _M_use_count drops to zero, to release                                                                        
  // the resources managed by *this.                                                                                                        
  virtual void
  dispose() = 0; // nothrow  

Может быть причина в плохом управлении shared_ptr, и я должен вернуться к обычному указателю?

Обновление:
еще один тест с похожим результатом:

int kkk = 1214 int c = fooBoxes [x] [y] [z] .size ();while (c> = 0) {aFoo = foosBoxes [x] [y] [z] [c--];printf ("% i \ t, kkk); fflush (stdout);}

На этот раз программа сломалась в третьей итерации. Если проблема была в неправильном размещении, то программа должна была потерпеть крах в первойитерация (в противоположном направлении программа завершает работу на первой итерации).

Ответы [ 5 ]

1 голос
/ 17 августа 2011
//some stuff which does not have an effect on fooit;

Но как материал влияет на foosBoxes [x] [y] [z]? В частности это удаляет элементы или вызывает перемещение вектора? Если это так, то fooit нельзя сравнивать по значению с foosBoxes [x] [y] [z] .end ().

Кроме того, что происходит с aFoo в цикле? Если получено недопустимое значение, его присвоение позже приведет к неопределенному поведению.

Попробуйте удалить some stuff из цикла. Если это работает, материал содержит ошибку. Если цикл по-прежнему не работает, причиной должно быть недопустимое значение в fooxBoxes [], прежде чем вводить цикл

У меня нет опыта работы с ValGrind. Но я использовал подобные продукты. Пожалуйста, убедитесь, что вы настроили ValGrind на самые строгие настройки. Это может сделать его мучительно медленным, но, надеюсь, найдет ошибку.

0 голосов
/ 19 августа 2011

Я пришел к выводу, что проблема была с использованием vector неправильно, так как я обновляю его через код.Я не знаю, как работает управление памятью в c++, но я полагаю, что произошло некоторое перекрытие двух векторов.Я перешел на set и теперь все работает

0 голосов
/ 17 августа 2011

Запустите ваш код с помощью libstdc ++ в режиме отладки .Он будет выполнять дополнительные проверки итераторов, контейнеров и алгоритмов и, надеюсь, поможет найти ошибку.

0 голосов
/ 17 августа 2011

Чтобы оперировать с элементом foosBoxes[x][y][z], вы также можете попробовать:

while (fooit != foosBoxes[x][y][z].end()){
      vector<std::tr1::shared_ptr<foo> > *aFoo = *fooit; 
       fooit++;
      //To use the object 
     // use it as   aFoo->method()  
 }

Не уверен, что я правильно понял.Но в настоящее время я использую указатели для итерации в моих объектах.

0 голосов
/ 17 августа 2011

Вы код, как он выглядит хорошо, единственное, что я могу думать, это то, что x y z действительны?operator[] не проверяет границы ...

...