Sinyal fatal 11 (SIGSEGV)

Saya mengalami kesalahan aneh dan saya tidak dapat menemukan dari mana asalnya. Satu-satunya hal yang muncul di logcat adalah:

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

Saya tidak langsung mendapatkan kesalahan ini saat menjalankan aplikasi, saya mendapatkannya setelah jangka waktu tertentu (antara 1 menit hingga 5 menit). Saya tidak dapat mereproduksi kesalahan ini, sepertinya acak dan karena tidak ada informasi lain, sulit untuk melakukan debug. Saya mencoba menambahkan beberapa informasi log ke perpustakaan saya tetapi saya masih tidak bisa mengatakan di mana kerusakan itu terjadi.

Saya menjalankan aplikasi yang sama sebanyak x kali dan mendapatkan alamat SIGSEGV yang berbeda (terkadang alamatnya sama seperti sebelumnya:

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)

Aplikasi saya menggunakan perpustakaan c++ yang memiliki NetworkThread yang menerima pembaruan dari server. Di sisi Java ada WorkerThread yang memeriksa apakah ada pembaruan baru dari NetworkThread dan jika ada pembaruan baru, ia akan memberi tahu semua pendengar. Saya juga memiliki LocationSpotter (di sisi Java) yang melakukan beberapa panggilan JNI ketika lokasi diperbarui.

Apakah ada cara untuk men-debug ini atau menggunakan alamat yang saya dapatkan dari SIGSEGV untuk men-debug aplikasi? Saya juga menggunakan objek JavaVM bersama untuk beberapa metode untuk mengambil JNIEnv saat ini (dan memanggil AttachCurrentThread). Apakah thread itu aman?

Saya perhatikan bahwa saya masih menerima pembaruan dari NetworkThread setelah saya mendapatkan kesalahan SIGSEGV (sebelum aplikasi benar-benar mogok). Itu berarti NetworkThread mungkin berfungsi.

Saya juga memperhatikan baris yang mungkin menjadi sumber masalah saya (dalam metode notifyAll) karena pesan terakhir yang dicetak sebelum SIGSEGV adalah "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");

Logcatnya:

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)

Saya kemudian mencoba mencetak log di baris pertama metode update setiap pendengar tetapi tidak ada satupun yang dicetak (yang menurut saya sangat aneh).

Bantuan apa pun akan sangat dihargai


person Fr4nz    schedule 10.01.2013    source sumber
comment
Bisakah Anda menambahkan file batu nisan terkait dari direktori /data/tombstones jika ada yang dibuat setelah kerusakan Anda?   -  person auselen    schedule 10.01.2013
comment
Saya tidak dapat menemukan file batu nisan. Saya mencoba menggunakan perspektif DDMS -› File Explorer -› data -› data -› (Paket Anda) -› files -› (File Anda) tetapi tidak ada apa-apa... Saya juga mencobanya di telepon tetapi tidak ada lagi hasil   -  person Fr4nz    schedule 11.01.2013
comment
Ngomong-ngomong, tahukah Anda mengapa tidak ada apa pun di bawah direktori data di ponsel saya? Haruskah saya melakukan root pada ponsel saya agar dapat membaca file batu nisan? (stackoverflow.com/a/8921133/1304830)   -  person Fr4nz    schedule 11.01.2013
comment
Pada dasarnya, Anda melakukan dereferensi penunjuk yang tidak valid, mungkin dalam kode Anda dengan menyerahkannya ke kode perpustakaan sistem, atau kecil kemungkinannya memicu bug platform. Hal utama yang ingin Anda temukan adalah tumpukan dump asli dari kerusakan tersebut, apakah ada kemungkinan itu sudah ada di logcat Anda?. Direktori /data tingkat atas tidak dapat diakses pada perangkat aman, tetapi Anda mungkin dapat melakukan cd ke direktori tertentu di bawahnya dari shell adb. Atau Anda mungkin dapat mereplikasi masalah pada emulator, yang shell adbnya sudah di-root.   -  person Chris Stratton    schedule 24.09.2013
comment
Bagaimana Anda mengaktifkan pengecualian dalam kode asli Anda? STL mana yang Anda gunakan?   -  person Alex Cohn    schedule 28.12.2013


Jawaban (3)


Sering kali kesalahan sinyal fatal terjadi ketika Anda mencoba mengakses objek apa pun yang tidak dibuat pada saat itu. Jadi periksalah dengan benar.

person Singhak    schedule 25.07.2013

Saya yakin Anda harus menulis ulang perulangan notifyAll seperti ini:

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);
    }
  • dalam kode asli Anda, cek hanya dicetak untuk dicatat, tetapi update() masih gagal (@Robin memperhatikan ini)
  • dalam kode asli Anda, pendengar bisa mendapatkan NULL yang tidak valid antara centang dan update()
  • bahkan setelah perubahan di atas, update() bisa mogok jika objek pendengar yang ditunjuk oleh listeners.at(i) menjadi tidak valid.

Namun mungkin saja crash terjadi karena penanganan pengecualian. Anda tidak mengungkapkan kode catch(...), jadi saya tidak dapat membicarakan hal ini.

person Alex Cohn    schedule 29.12.2013

Tampaknya sudah jelas

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

seharusnya

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