menetapkan nilai dari vektor (penunjuk bersama) ke penunjuk bersama menyebabkan kesalahan segmentasi c++

Dalam kode saya, saya memiliki vector <vector <vector <vector <std::tr1::shared_ptr<foo> > > > > bernama foosBoxes. Vektor bersarang mempunyai peran mensimulasikan posisi kotak fisik. Saya juga memiliki loop sementara yang menyebabkan kesalahan segmentasi:

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;
}

Beberapa hal yang telah saya coba:
1. Saya telah mencoba menggunakan aFoo = *fooit++ tetapi tidak berhasil.
2. Kesalahan segmentasi terjadi kira-kira setelah beberapa perseribu putaran yang berjalan dengan baik.
3. Saya telah mencoba mencoba mengatasi masalah valgrind dan valgrind menyelesaikan langkah tersebut.
4. Dalam loop yang macet, saya telah mencetak penghitung yang berjalan sebelum dan sesudah baris yang dicurigai. ketika sebelum garis, saya mendapatkan 8 cetakan (ukuran vektor) dan ketika setelahnya saya mendapatkan 7 cetakan.

Bagaimana saya bisa mengetahui hal ini?

Pembaruan:
Saya telah menambahkan loop untuk dijalankan sebelum loop utama:

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);
}

Yang menghasilkan hasil yang sama.

Pembaruan:
menurut gdb:

Program menerima sinyal SIGSEGV, kesalahan segmentasi. 0x000000000043e400 diputar (kkk=1214) di /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/tr1/boost_shared_ptr. h:153 153 buang();

Saya pikir fungsi yang sesuai di boost_shared_ptr.h adalah

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() didefinisikan di tempat lain dalam file:

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

Mungkinkah alasannya adalah pengelolaan shared_ptr yang buruk dan saya harus beralih kembali ke penunjuk biasa?

Pembaruan:
tes lain dengan hasil serupa:

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

Kali ini program crush pada iterasi ketiga. Jika masalahnya ada pada alokasi yang salah, maka program tersebut seharusnya mengalami crash pada iterasi pertama (berlawanan dengan arah program crash pada iterasi pertama).


person Yotam    schedule 17.08.2011    source sumber
comment
Dari apa yang Anda katakan, sepertinya ada kode di tempat lain yang memunculkan perilaku tidak terdefinisi. Sudahkah Anda mencoba menjalankannya dengan valgrind atau alat serupa untuk platform Anda?   -  person Flexo    schedule 17.08.2011
comment
@awoodland: ya saya mencoba valgrind (nomor 3 pada daftar hal yang saya coba) masalahnya adalah valgeind selamat dari langkah ini...   -  person Yotam    schedule 17.08.2011
comment
Coba aktifkan semua jenis mode debug (dari segi kompiler dan perpustakaan) dan coba kurangi kode Anda seminimal mungkin untuk mengisolasi kesalahan.   -  person sellibitze    schedule 17.08.2011


Jawaban (5)


Jalankan kode Anda dengan libstdc++ dalam mode debug. Ini akan melakukan pemeriksaan ekstra terhadap iterator, container dan algoritma dan mudah-mudahan akan membantu menemukan bug.

person ks1322    schedule 17.08.2011
comment
Bagaimana cara menjalankan libstdc++? Saya memiliki kompiler gcc dan g++ di mesin saya. - person Yotam; 17.08.2011
comment
Baca Menggunakan Mode Debug. Untuk menggunakan mode debug libstdc++, kompilasi aplikasi Anda dengan flag compiler -D_GLIBCXX_DEBUG dan jalankan kembali kode Anda. Mudah-mudahan itu akan macet karena beberapa tindakan yang tidak valid. - person ks1322; 17.08.2011
comment
libstdc++ adalah perpustakaan bersama yang mengimplementasikan Perpustakaan C++ Standar. Itu dikirimkan dengan kompiler g++. - person ks1322; 17.08.2011
comment
Saya telah mencobanya dan mendapatkan kesalahan mencoba membandingkan iterator tunggal dengan iterator masa lalu Saya sekarang mencoba mencari penyebabnya (fungsi spesifik tidak dicetak) - person Yotam; 17.08.2011
comment
Jika itu terjadi (saya kira seharusnya begitu), Anda dapat menjalankannya di bawah gdb dan menghentikan pengecualian. Ini akan menghentikan Anda tepat di tempat di mana masalah terdeteksi. - person Tomek; 17.08.2011
comment
Bagaimana cara memeriksa apakah suatu nilai sah (baik gdb atau di dalam kode)? Saya curiga saya telah menghilangkan penunjuk dari vektor tetapi iterator akhir tidak diperbarui... - person Yotam; 17.08.2011
comment
Menurut pesan kesalahan Anda membandingkan beberapa iterator yang tidak valid dengan iterator akhir. Satu-satunya tempat terjadinya hal ini adalah while (fooit != foosBoxes[x][y][z].end()){. Jadi saya kira suatu saat iterator fooit menjadi tidak valid. - person ks1322; 17.08.2011

//some stuff which does not have an effect on fooit;

Tetapi apakah hal tersebut berpengaruh pada foosBoxes[x][y][z]? Khususnya apakah ini menghilangkan elemen atau menyebabkan relokasi vektor? Jika demikian, fooit tidak dapat dibandingkan secara bermakna dengan foosBoxes[x][y][z].end().

Juga, apa yang terjadi pada aFoo di loop? Jika nilai ini tidak valid, penetapannya nanti akan menyebabkan perilaku tidak terdefinisi.

Coba hapus some stuff dari loop. Jika berhasil, berarti ada bug. Jika loop masih gagal, penyebabnya harus berupa nilai yang tidak valid di fooxBoxes[] sebelum Anda memasuki loop

Saya tidak punya pengalaman dengan ValGrind. Tapi saya sudah menggunakan produk serupa. Harap periksa apakah Anda telah mengonfigurasi ValGrind ke pengaturan paling ketatnya. Ini mungkin membuat penggunaannya sangat lambat, tapi semoga menemukan bugnya.

person Leo    schedule 17.08.2011
comment
Pengalaman saya dengan valgrind hampir sama terbatasnya dengan pengalaman Anda... fooBoxes tidak berubah selama loop tetapi mungkin diubah di tempat lain dan memiliki efek. Saya sedang memeriksa yang kedua sekarang. - person Yotam; 17.08.2011
comment
Oke, saya telah menambahkan loop untuk dijalankan sebelum loop utama, silakan baca pembaruan saya untuk pertanyaan tersebut - person Yotam; 17.08.2011
comment
Saya harus setuju - bagi saya sepertinya Anda menyebabkan vektor itu mengalokasikan ulang dan menghancurkan iteratornya. - person Puppy; 17.08.2011
comment
@DeadMG: Saya mencoba mengulangi ke arah lain dan program tidak terhenti pada iterasi pertama. Silakan baca tambahan saya untuk pertanyaan itu. Saya juga telah mengulangi semua foos (vektor terpisah) dan tidak ada yang hancur di sana. Apakah Anda tahu bagaimana cara mencetak konten vektor int gdb? - person Yotam; 17.08.2011

Kode Anda terlihat oke, satu-satunya hal yang terpikir oleh saya adalah apakah x y z valid? operator[] tidak memeriksa batas...

person Nim    schedule 17.08.2011
comment
Saya akan mengujinya dengan menggunakan at() daripada operator... mungkin mengungkapkan... - person Nim; 17.08.2011

Saya sampai pada kesimpulan bahwa masalahnya adalah penggunaan vector salah karena saya memperbaruinya melalui kode. Saya tidak tahu cara kerja manajemen memori di c++ tetapi saya yakin terjadi semacam tumpang tindih antara dua vektor. Saya telah beralih ke set dan semuanya berfungsi sekarang

person Yotam    schedule 19.08.2011

Untuk mengoperasikan elemen foosBoxes[x][y][z] Anda juga dapat mencoba:

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()  
 }

Tidak yakin apakah saya menyampaikan maksudnya. Tetapi saat ini saya menggunakan pointer untuk mengulangi objek saya.

person Shubhendu Sinha    schedule 17.08.2011