Debug Xcode 4.2 tidak melambangkan panggilan stack

140

Saya memiliki masalah dengan debugging Xcode 4.2 di simulator / perangkat iOS 5. Kode berikut macet, seperti yang diharapkan:

NSArray *arr=[NSArray array];
[arr objectAtIndex:100];

Di iOS 4, saya mendapatkan jejak tumpukan nomor hex yang bermanfaat. Tetapi di iOS 5, itu hanya memberi saya:

*** First throw call stack:
(0x16b4052 0x1845d0a 0x16a0674 0x294c 0x6f89d6 0x6f98a6 0x708743 0x7091f8 0x7fcaa9 0x2257fa9 0x16881c5 0x15ed022 0x15eb90a 0x15eadb4 0x15eaccb 0x6f02a7 0x6faa93 0x2889 0x2805)

Terima kasih.

cekisakurek
sumber

Jawaban:

256

Tidak ada yang saya coba untuk memperbaikinya (mencoba kedua kompiler, kedua debugger, dll.) Setelah memutakhirkan XCode untuk pembaruan iOS 5, tampaknya tidak ada jejak tumpukan yang berfungsi.

Namun, saya telah menemukan solusi yang efektif - membuat penangan pengecualian saya sendiri (yang juga berguna untuk alasan lain). Pertama, buat fungsi yang akan menangani kesalahan dan output ke konsol (serta apa pun yang ingin Anda lakukan dengannya):

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

Selanjutnya, tambahkan penangan pengecualian ke delegasi aplikasi Anda:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Normal launch stuff
}

Itu dia!

Jika ini tidak berhasil, maka hanya ada dua kemungkinan alasan :

  1. Sesuatu menimpa NSSetUncaughtExceptionHandlerpanggilan Anda (hanya ada satu penangan untuk seluruh aplikasi Anda). Misalnya, beberapa perpustakaan pihak ke-3 mengatur uncaughtExceptionHandler mereka sendiri. Jadi, cobalah mengaturnya di AKHIR didFinishLaunchingWithOptionsfungsi Anda (atau menonaktifkan pustaka pihak ketiga secara selektif). Atau lebih baik lagi, atur break point simbolis NSSetUncaughtExceptionHandleruntuk segera melihat siapa yang memanggilnya. Yang mungkin ingin Anda lakukan adalah memodifikasi yang sekarang daripada menambahkan yang lain.
  2. Anda tidak benar-benar menghadapi pengecualian (misalnya, EXC_BAD_ACCESSadalah bukan pengecualian, kredit komentar @Erik B, di bawah)
Zane Claes
sumber
1
Senang mendengarnya :) Saya merasa bermanfaat untuk menulis crash log ke file dan meminta pengguna untuk mengirimkannya pada peluncuran berikutnya (hanya dalam mode rilis, untuk tidak menghalangi debugging). Ini memungkinkan saya mendapatkan laporan bug yang luar biasa ... dan pengguna tahu bahwa masalah mereka sedang diatasi :)
Zane Claes
2
Ini sepertinya tidak berhasil - uncaughtExceptionHandlerrutinitas tidak pernah diminta.
Hot Licks
1
Bisakah Anda lebih spesifik tentang cara menggunakannya? Sepertinya itu tidak berhasil untuk saya.
Danut Pralea
1
XCode yang cukup menyedihkan tidak menampilkan ini untuk kita.
Authman Apatira
1
Sangat dihargai! Sangat membingungkan bahwa Apple tidak mengimplementasikan fungsi dasar semacam ini ke dalam IDE.
devios1
110

Ada opsi yang berguna untuk menambahkan Exception Breakpoint (menggunakan + di bagian bawah Breakpoint Navigator). Ini akan berhenti pada Pengecualian apa pun (atau Anda dapat mengatur kondisi). Saya tidak tahu apakah pilihan ini baru di 4.2 atau jika saya akhirnya menyadari bahwa ini mencoba menyelesaikan masalah simbol yang hilang.

Setelah Anda mencapai breakpoint ini Anda dapat menggunakan Debug Navigator untuk menavigasi tumpukan panggilan, memeriksa variabel, dll seperti biasa.

Jika Anda menginginkan tumpukan panggilan simbolis yang cocok untuk disalin / ditempel atau sejenisnya, gtrb backtrace akan berfungsi dengan baik dari sana:

(gdb) bt
#0  0x01f84cf0 in objc_exception_throw ()
#1  0x019efced in -[NSObject doesNotRecognizeSelector:] ()

(dll)

WiseOldDuck
sumber
3
Sejauh ini ini bekerja dengan baik untuk saya. Debugger berhenti di jalur menerjang sekarang, tidak perlu untuk backtrace.
Tim
1
Ini juga cocok untuk saya. Terima kasih banyak, saya menjadi gila tanpa breakpoint ini ...
William Denniss
+1 untuk itu berhasil. Itu tidak memberi Anda pesan kesalahan yang bagus menjelaskan alasan pengecualian, tapi ini awal ...
Nicu Surdu
Anda adalah HotD @WiseOldDuck saya.
Maverick1st
Ini mengembalikan perilaku yang diharapkan untuk saya. CATATAN: Ingat juga untuk menambahkan kembali breakpoint ini pada proyek baru!
MechEthan
46

Ada fitur baru pada debugger. Anda dapat mengatur break point kapan saja pengecualian dilemparkan dan menghentikan eksekusi di sana, seperti yang biasanya terjadi pada 4.0.

Pada "Breakpoint Navigator", tambahkan "Exception Breakpoint" dan cukup tekan "Done" pada popup opsi.

Itu saja!

PS: Dalam beberapa kasus akan lebih baik untuk istirahat hanya untuk pengecualian Objective-C.

Pedro
sumber
Pasti ini solusinya buat saya.
bradgonesurfing
Ini masalah bagi saya. Seorang kolega dan saya berbagi proyek Xcode yang sama dan saya bertanya kepadanya apakah dia punya masalah, dan dia tidak. Perbedaannya adalah bahwa proyeknya melanggar pengecualian objektif-c (objc_exception_throw)
horseshoe7
Anda baru saja membantu menemukan bug yang tidak bisa dilacak. Terima kasih banyak. Saya telah mencari di mana-mana untuk sesuatu seperti ini.
rjgonzo
1
Ini bekerja seperti pesona! Itulah tepatnya yang saya cari, ini lebih baik daripada menambahkan Exception Handler karena menambahkan Breakpoint dapat membawa Anda langsung ke tempat pengecualian dilemparkan, handler pengecualian bekerja tetapi hanya memberi Anda ide.
im8bit
21

Ini adalah satu solusi lagi, tidak seanggun sebelumnya, tetapi jika Anda tidak menambahkan breakpoint atau handler pengecualian, itu bisa menjadi satu-satunya cara.
Saat aplikasi mogok, dan Anda mendapatkan tumpukan panggilan lempar mentah pertama (dalam angka hex), ketikkan ke konsol Xcode info line *hex(jangan lupa tanda bintang dan 0xhex specifier), misalnya:

(gdb) info line *0x2658
Line 15 of "path/to/file/main.m" starts at address 0x25f2 <main+50>
and ends at 0x267e <main+190>.

Jika Anda menggunakan lldb , Anda dapat mengetik image lookup -a hex(tanpa tanda bintang dalam situasi ini), dan Anda mendapatkan hasil yang serupa.

Dengan metode ini, Anda dapat melintasi dari atas tumpukan lemparan (akan ada sekitar 5-7 penyebar pengecualian sistem) ke fungsi Anda yang menyebabkan kerusakan, dan menentukan file dan baris kode yang tepat.

Juga, untuk efek serupa Anda dapat menggunakan utilitas atos di terminal, cukup ketik:

atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...

dan Anda mendapatkan jejak stack yang dilambangkan (setidaknya untuk fungsi Anda memiliki simbol debug). Metode ini lebih disukai, karena Anda tidak memiliki untuk setiap panggilan alamat info line, cukup salin alamat dari output konsol dan tempelkan ke terminal.

Alexander
sumber
9

Anda dapat menambahkan Exception Breakpoint (menggunakan + di bagian bawah Breakpoint Navigator) dan menambahkan action bt ke dalamnya (klik tombol Add Action, pilih Debugger Command, masukkan "bt" di bidang teks). Ini akan menampilkan jejak tumpukan segera setelah pengecualian dilemparkan.

MonsieurDart
sumber
6

Ini adalah masalah umum, tidak mendapatkan jejak stack di 4.2. Anda dapat mencoba bertukar antara LLDB dan GDB untuk melihat apakah Anda mendapatkan hasil yang lebih baik.

Ajukan laporan bug di sini.

http://developer.apple.com/bugreporter/

EDIT:

Saya percaya bahwa jika Anda menukar kembali ke LLVM GCC 4.2 Anda tidak akan melihat ini terjadi. Anda mungkin kehilangan fitur yang Anda butuhkan.

logancautrell
sumber
ya saya mencoba mengganti kompiler, namun masalah tetap ada. tapi terima kasih lagian :)
cekisakurek
Dia menyarankan untuk mengganti debugger, bukan compiler.
bames53
1
FYI: Dalam hal ini, tidak ada hubungannya dengan versi kompiler atau debugger yang Anda gunakan. Ini adalah perubahan dalam output konsol dari iOS.
clarkcox3
Menarik berapa banyak pengalaman ini bervariasi - saya pikir ada beberapa masalah. Saya tidak bisa membuat debugger berhenti pada breakpoint pengecualian. Beralih dari GDB ke LLDB memecahkan masalah.
Matt
6

Gunakan kode ini di fungsi utama Anda:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    int retVal;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException *exception) {
        NSLog(@"CRASH: %@", exception);
        NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    }
    @finally {
        [pool release];
    }
    return retVal;
}
wilson lin
sumber
Ini sepertinya tidak bekerja dengan storyboard. 2012-06-04 20: 34: 52.211 Masalah [1944: 207] Delegasi aplikasi harus mengimplementasikan properti jendela jika ingin menggunakan file papan cerita utama. 2012-06-04 20: 34: 52.213 Masalah [1944: 207] Aplikasi diharapkan memiliki pengontrol tampilan root di akhir peluncuran aplikasi
macasas
6

Pada jenis prompt konsol debug Xcode:

image lookup -a 0x1234

Dan itu akan menunjukkan kepada Anda sesuatu seperti:

  Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
  Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202
Matt Connolly
sumber
Terima kasih, saya benar-benar mencari ini. Mengejutkan tidak ada jalan pintas untuk menampilkan seluruh "tumpukan panggilan panggilan pertama" sebagai tumpukan panggilan, karena saya kira skrip Python lldb dapat dengan mudah ditulis.
Ilya
1

Mengaktifkan 'Kompilasi untuk Ibu Jari' (konfigurasi debug) berhasil untuk saya.

Bradweiser86
sumber