การกำหนดค่าจากเวกเตอร์ (ของตัวชี้ที่ใช้ร่วมกัน) ให้กับตัวชี้ที่ใช้ร่วมกันทำให้เกิดข้อผิดพลาดในการแบ่งส่วน c ++

ในรหัสของฉัน ฉันมี vector <vector <vector <vector <std::tr1::shared_ptr<foo> > > > > ชื่อ foosBoxes เวกเตอร์ที่ซ้อนกันมีบทบาทในการจำลองตำแหน่งฟิสิคัลบ็อกซ์ ฉันยังมี while loop ซึ่งทำให้เกิดข้อผิดพลาดในการแบ่งส่วน:

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 ปัญหา และ 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 กำจัด();

ฉันคิดว่าฟังก์ชั่นที่เหมาะสมใน 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(); ในขณะที่ (c >= 0){ aFoo = foosBoxes[x][y][z][c--]; printf("%i\t, kkk); fflush(stdout); }

คราวนี้โปรแกรมสนใจในการวนซ้ำครั้งที่สาม หากปัญหาเกิดจากการจัดสรรที่ไม่ถูกต้อง โปรแกรมควรมีการทับซ้อนในการวนซ้ำครั้งแรก (ในทิศทางตรงกันข้าม โปรแกรมจะขัดข้องในการวนซ้ำครั้งแรก)


person Yotam    schedule 17.08.2011    source แหล่งที่มา
comment
จากสิ่งที่คุณพูดดูเหมือนว่าโค้ดบางตัวกำลังเรียกใช้พฤติกรรมที่ไม่ได้กำหนดไว้ คุณได้ลองใช้ valgrind หรือเครื่องมือที่คล้ายกันสำหรับแพลตฟอร์มของคุณแล้วหรือยัง?   -  person Flexo    schedule 17.08.2011
comment
@awoodland: ใช่ ฉันลอง valgrind (หมายเลข 3 ในสิ่งที่ฉันลองรายการ) ปัญหาคือ valgeind รอดชีวิตจากขั้นตอนนี้...   -  person Yotam    schedule 17.08.2011
comment
ลองเปิดใช้งานโหมดแก้ไขข้อบกพร่องทุกประเภท (แบบคอมไพเลอร์และแบบไลบรารี) และพยายามลดโค้ดของคุณให้เหลือน้อยที่สุดเพื่อแยกข้อผิดพลาด   -  person sellibitze    schedule 17.08.2011


คำตอบ (5)


เรียกใช้โค้ดด้วย libstdc++ ในโหมดแก้ไขข้อบกพร่อง มันจะตรวจสอบตัววนซ้ำ คอนเทนเนอร์ และอัลกอริธึมเพิ่มเติม และหวังว่าจะช่วยค้นหาจุดบกพร่องได้

person ks1322    schedule 17.08.2011
comment
ฉันจะรัน libstdc++ ได้อย่างไร ฉันมีคอมไพเลอร์ gcc และ g++ บนเครื่องของฉัน - person Yotam; 17.08.2011
comment
อ่าน การใช้โหมดแก้ไขข้อบกพร่อง หากต้องการใช้โหมดดีบัก libstdc++ ให้คอมไพล์แอปพลิเคชันของคุณด้วยแฟล็กคอมไพเลอร์ -D_GLIBCXX_DEBUG แล้วรันโค้ดของคุณอีกครั้ง หวังว่ามันจะขัดข้องกับการกระทำที่ไม่ถูกต้องบางอย่าง - person ks1322; 17.08.2011
comment
libstdc++ เป็นไลบรารีที่ใช้ร่วมกันที่ใช้ไลบรารี Standard C++ มันมาพร้อมกับคอมไพเลอร์ g++ - person ks1322; 17.08.2011
comment
ฉันได้ลองแล้วและได้รับข้อผิดพลาด พยายามเปรียบเทียบตัววนซ้ำเอกพจน์กับตัววนซ้ำที่ผ่านมา ฉันกำลังพยายามค้นหาสาเหตุของสิ่งนั้น (ไม่ได้พิมพ์ฟังก์ชันเฉพาะ) - person Yotam; 17.08.2011
comment
ถ้ามันกำลังขว้าง (ฉันเดาว่ามันควรจะ) คุณสามารถทำงานภายใต้ gdb และทำลายข้อยกเว้นได้ สิ่งนี้ควรหยุดคุณในตำแหน่งที่ตรวจพบปัญหา - person Tomek; 17.08.2011
comment
ฉันจะตรวจสอบได้อย่างไรว่าค่านั้นถูกกฎหมาย (ทั้ง gdb หรือภายในโค้ด) ฉันสงสัยว่าฉันได้ลบตัวชี้ออกจากเวกเตอร์แล้ว แต่ตัววนซ้ำจุดสิ้นสุดไม่ได้รับการอัพเดต... - person Yotam; 17.08.2011
comment
ตามข้อความแสดงข้อผิดพลาด คุณกำลังเปรียบเทียบตัววนซ้ำที่ไม่ถูกต้องกับตัววนซ้ำ end ที่เดียวที่มันเกิดขึ้นคือ while (fooit != foosBoxes[x][y][z].end()){ ดังนั้นฉันเดาว่าในบางจุดตัววนซ้ำ fooit จะไม่ถูกต้อง - person ks1322; 17.08.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 เป็นการตั้งค่าที่เข้มงวดที่สุดแล้ว นี่อาจทำให้การใช้งานช้าลงอย่างเจ็บปวด แต่หวังว่าจะพบจุดบกพร่อง

person Leo    schedule 17.08.2011
comment
ประสบการณ์ของฉันกับ valgrind เกือบจะจำกัดพอๆ กับของคุณ... fooBoxes จะไม่เปลี่ยนแปลงระหว่างการวนซ้ำ แต่อาจมีการเปลี่ยนแปลงที่อื่นและมีผลกระทบ ฉันกำลังตรวจสอบอันที่สองอยู่ตอนนี้ - person Yotam; 17.08.2011
comment
ตกลง ฉันได้เพิ่มการวนซ้ำเพื่อทำงานก่อนการวนซ้ำหลัก โปรดอ่านการอัปเดตของคำถาม - person Yotam; 17.08.2011
comment
ฉันต้องเห็นด้วย - สำหรับฉันดูเหมือนว่าคุณกำลังทำให้เวกเตอร์นั้นจัดสรรใหม่และทำลายตัววนซ้ำ - person Puppy; 17.08.2011
comment
@DeadMG: ฉันพยายามวนซ้ำในทิศทางอื่นและโปรแกรมไม่ได้ถูกบดขยี้ในการวนซ้ำครั้งแรก โปรดอ่านคำถามเพิ่มเติมของฉัน ฉันยังได้วนซ้ำ foos ทั้งหมด (เวกเตอร์แยก) และไม่มีอะไรถูกบดขยี้ที่นั่น คุณรู้ไหมว่าฉันจะพิมพ์เนื้อหาของ vector int gdb ได้อย่างไร - person Yotam; 17.08.2011

คุณเป็นโค้ดเพราะมันดูโอเค สิ่งเดียวที่ฉันคิดได้คือ x y z ถูกต้องใช่ไหม operator[] ไม่มีการตรวจสอบขอบเขต...

person Nim    schedule 17.08.2011
comment
ฉันจะทดสอบโดยใช้ at() แทนโอเปอเรเตอร์... อาจจะเปิดเผย... - person Nim; 17.08.2011

ฉันได้ข้อสรุปว่าปัญหาอยู่ที่การใช้งาน vector ผิดตั้งแต่ฉันอัปเดตผ่านโค้ด ฉันไม่รู้ว่าการจัดการหน่วยความจำใน c++ ทำงานอย่างไร แต่ฉันเชื่อว่ามีการทับซ้อนกันระหว่างเวกเตอร์สองตัวเกิดขึ้น ฉันเปลี่ยนมาใช้ set และตอนนี้ทุกอย่างทำงานได้แล้ว

person Yotam    schedule 19.08.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()  
 }

ไม่แน่ใจว่าฉันกำลังทำประเด็นอยู่หรือไม่ แต่ตอนนี้ฉันกำลังใช้พอยน์เตอร์เพื่อวนซ้ำในวัตถุของฉัน

person Shubhendu Sinha    schedule 17.08.2011