สัญญาณร้ายแรง 11 (SIGSEGV)

ฉันมีข้อผิดพลาดแปลก ๆ และฉันไม่พบว่ามันมาจากไหน สิ่งเดียวที่ปรากฏใน logcat คือ:

01-10 17:07:10.665: A/libc(20449): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

ฉันไม่ได้รับข้อผิดพลาดนี้ทันทีเมื่อฉันเรียกใช้แอป แต่ได้รับข้อผิดพลาดนี้หลังจากสุ่มผ่านไประยะหนึ่ง (ประมาณ 1 นาทีถึง 5 นาที) ฉันไม่สามารถทำซ้ำข้อผิดพลาดนี้ได้ ดูเหมือนว่าจะเป็นการสุ่ม และเนื่องจากไม่มีข้อมูลอื่น จึงเป็นการยากที่จะแก้ไข ฉันพยายามเพิ่มข้อมูลบันทึกลงในไลบรารีของฉัน แต่ยังไม่สามารถบอกได้ว่าข้อขัดข้องเกิดขึ้นที่ใด

ฉันใช้งานแอปเดียวกัน x ครั้งและได้ที่อยู่ SIGSEGV ที่แตกต่างกัน (บางครั้งก็เป็นที่อยู่เดียวกันกับเมื่อก่อน:

01-10 17:29:04.650: A/libc(21588): Fatal signal 11 (SIGSEGV) at 0x6c707063 (code=1)

01-10 17:25:55.165: A/libc(21473): Fatal signal 11 (SIGSEGV) at 0x0069004c (code=1)

01-10 17:11:58.780: A/libc(20742): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

01-10 17:00:02.010: A/libc(20160): Fatal signal 11 (SIGSEGV) at 0x00000018 (code=1)

แอพของฉันกำลังใช้ไลบรารี c++ ที่มี NetworkThread ที่ได้รับการอัปเดตจากเซิร์ฟเวอร์ ฝั่ง Java มี WorkerThread ที่ตรวจสอบว่ามีการอัพเดตใหม่จาก NetworkThread และหากมีการอัพเดตใหม่จะแจ้งให้ผู้ฟังทั้งหมดทราบ ฉันยังมี LocationSpotter (ทางฝั่ง Java) ที่ทำการโทร JNI บางส่วนเมื่อมีการอัปเดตตำแหน่ง

มีวิธีแก้ไขข้อบกพร่องนี้หรือใช้ที่อยู่ที่ฉันได้รับจาก SIGSEGV เพื่อแก้ไขข้อบกพร่องของแอปหรือไม่ นอกจากนี้ฉันกำลังใช้วัตถุ JavaVM ที่ใช้ร่วมกันสำหรับบางวิธีในการดึงข้อมูล JNIEnv ปัจจุบัน (และเรียก AttachCurrentThread) เธรดนั้นปลอดภัยหรือไม่?

ฉันสังเกตเห็นว่าฉันยังคงได้รับการอัปเดตจาก NetworkThread หลังจากที่ฉันได้รับข้อผิดพลาด SIGSEGV (ก่อนที่แอปจะขัดข้องจริงๆ) นั่นหมายความว่า NetworkThread อาจจะใช้งานได้

ฉันยังสังเกตเห็นบรรทัดที่อาจเป็นสาเหตุของปัญหาของฉัน (ในวิธี notifyAll) เนื่องจากข้อความสุดท้ายที่พิมพ์ก่อน SIGSEGV คือ "notifyAll1" :

for (unsigned i = 0; i < listeners.size(); i++) {
    try {
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll1");
        if (listeners.at(i) == NULL)
            __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");


        listeners.at(i)->update(u); // <- This line is a potential suspect
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2");

ล็อกแคท :

01-10 17:07:10.665: I/FROM C++(20449): notifyAll1
01-10 17:07:10.665: A/libc(20449): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

ฉันพยายามพิมพ์บันทึกในบรรทัดแรกของวิธี update ของผู้ฟังแต่ละคน แต่ไม่มีการพิมพ์ใดเลย (ซึ่งฉันคิดว่าแปลกจริงๆ)

ความช่วยเหลือใด ๆ จะได้รับการชื่นชมอย่างมาก


person Fr4nz    schedule 10.01.2013    source แหล่งที่มา
comment
คุณสามารถเพิ่มไฟล์ tombstone ที่เกี่ยวข้องจาก /data/tombstones dir ได้หรือไม่ หากไฟล์นั้นถูกสร้างขึ้นหลังจากการชนของคุณ   -  person auselen    schedule 10.01.2013
comment
ฉันไม่พบไฟล์หลุมฝังศพ ฉันพยายามใช้มุมมอง DDMS -› File Explorer -› data -› data -› (แพ็คเกจของคุณ) -› ไฟล์ -› (ไฟล์ของคุณ) แต่ไม่มีอะไรเลย ... ฉันลองทางโทรศัพท์แล้วเช่นกัน แต่ไม่มีอีกแล้ว ผลลัพธ์   -  person Fr4nz    schedule 11.01.2013
comment
คุณรู้ไหมว่าทำไมไม่มีอะไรอยู่ในไดเร็กทอรีข้อมูลในโทรศัพท์ของฉัน ฉันควรรูทโทรศัพท์เพื่อให้สามารถอ่านไฟล์หลุมฝังศพได้หรือไม่? (stackoverflow.com/a/8921133/1304830)   -  person Fr4nz    schedule 11.01.2013
comment
โดยพื้นฐานแล้ว คุณกำลังอ้างอิงตัวชี้ที่ไม่ถูกต้อง ซึ่งอาจอยู่ในโค้ดของคุณโดยการมอบตัวชี้ให้กับโค้ดไลบรารีระบบ หรือมีโอกาสน้อยมากที่จะทำให้เกิดข้อบกพร่องของแพลตฟอร์ม สิ่งหลักที่คุณต้องการค้นหาคือไฟล์เนทิฟสแต็กดัมพ์ของข้อขัดข้อง มีโอกาสใดบ้างที่อยู่ใน logcat ของคุณ? ไม่สามารถเข้าถึงไดเร็กทอรี /data ระดับบนสุดบนอุปกรณ์ที่มีการรักษาความปลอดภัย แต่คุณอาจสามารถ cd ไปยังไดเร็กทอรีเฉพาะด้านล่างจากเชลล์ adb หรือคุณอาจจำลองปัญหาบนโปรแกรมจำลองได้ โดยที่ adb เชลล์เป็นรูทอยู่แล้ว   -  person Chris Stratton    schedule 24.09.2013
comment
คุณเปิดใช้งานข้อยกเว้นในโค้ดเนทีฟของคุณได้อย่างไร คุณใช้ STL ใด?   -  person Alex Cohn    schedule 28.12.2013


คำตอบ (3)


ข้อผิดพลาดร้ายแรงของสัญญาณส่วนใหญ่เกิดขึ้นเมื่อคุณพยายามเข้าถึงวัตถุใด ๆ ที่ไม่ได้สร้างขึ้นในขณะนั้น ดังนั้นควรตรวจสอบให้ถูกต้อง

person Singhak    schedule 25.07.2013

ฉันเชื่อว่าคุณควรเขียนลูป notifyAll ใหม่ดังนี้:

for (unsigned i = 0; i < listeners.size(); i++) {
  try {
    __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll1 i=%u", i);
    auto listener = *listeners.at(i);

    if (&listener == NULL) {
      __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");
    }
    else {
      __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2 : listener[%u] at %p", i, &listener);
      listener.update(u);
    }
  • ในรหัสเดิมของคุณ เช็คพิมพ์เพื่อบันทึกเท่านั้น แต่ update() จะยังคงล้มเหลว (@Robin สังเกตเห็นสิ่งนี้)
  • ในโค้ดเดิมของคุณ listener อาจได้รับ NULL ที่ไม่ถูกต้องระหว่างการตรวจสอบและ update()
  • แม้ว่าการเปลี่ยนแปลงข้างต้น update() อาจหยุดทำงานหากออบเจ็กต์ Listener ที่ listeners.at(i) ชี้ไปนั้นไม่ถูกต้อง

แต่เป็นไปได้ว่าความผิดพลาดเกิดขึ้นเนื่องจากการจัดการข้อยกเว้น คุณไม่ได้เปิดเผยรหัส catch(...) ดังนั้นฉันจึงไม่สามารถพูดถึงเรื่องนี้ได้

person Alex Cohn    schedule 29.12.2013

ดูเหมือนว่าจะชัดเจน

if (listeners.at(i) == NULL)
            __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");


        listeners.at(i)->update(u); // <- This line is a potential suspect
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2");

ควรจะเป็น

if (listeners.at(i) == NULL) {
    __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");
} else {
    listeners.at(i)->update(u); // <- This line is a potential suspect
    __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2");
}
person Robin    schedule 27.11.2013