iOS
Błędy debugowania
Szukaj…
Znajdowanie informacji o awarii
Gdy aplikacja ulegnie awarii, Xcode wejdzie do debuggera i wyświetli więcej informacji o awarii:
Najważniejsze części to:
Czerwona strzałka
Czerwona strzałka pokazuje, która linia kodu uległa awarii i dlaczego się zawiesiła.
Konsola debuggera
Wiele awarii rejestruje więcej informacji w konsoli debuggera. Powinien pojawić się automatycznie po awarii aplikacji, ale jeśli go nie ma, pokaż debuger, wybierając opcję przycisk w prawym górnym rogu Xcode i wyświetl konsolę, klikając przycisk w prawym dolnym rogu debuggera.
Ślad stosu
Śledzenie stosu zawiera listę funkcji, z których pochodzi program, zanim dotarł do kodu, który się zawiesił.
Część śladu stosu jest wyświetlana w Nawigatorze debugowania po lewej stronie ekranu, a elementy sterujące debugera pozwalają wybrać ramkę stosu do wyświetlenia w debuggerze:
Jeśli wpiszesz polecenie bt
wierszu polecenia (lldb)
w debuggerze i naciśniesz return , otrzymasz tekstową reprezentację śladu stosu, którą możesz skopiować i wkleić:
(lldb) bt
* thread #1: tid = 0x3aaec5, 0x00007fff91055f06 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff91055f06 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x000000010008142d libsystem_pthread.dylib`pthread_kill + 90
frame #2: 0x00007fff96dc76e7 libsystem_c.dylib`abort + 129
frame #3: 0x00007fff8973bf81 libc++abi.dylib`abort_message + 257
frame #4: 0x00007fff89761a47 libc++abi.dylib`default_terminate_handler() + 267
frame #5: 0x00007fff94f636ae libobjc.A.dylib`_objc_terminate() + 103
frame #6: 0x00007fff8975f19e libc++abi.dylib`std::__terminate(void (*)()) + 8
frame #7: 0x00007fff8975ec12 libc++abi.dylib`__cxa_throw + 121
frame #8: 0x00007fff94f6108c libobjc.A.dylib`objc_exception_throw + 318
frame #9: 0x00007fff8d067372 CoreFoundation`-[__NSPlaceholderArray initWithObjects:count:] + 290
frame #10: 0x00007fff8d0eaa1f CoreFoundation`+[NSArray arrayWithObject:] + 47
* frame #11: 0x0000000100001b54 test`main(argc=1, argv=0x00007fff5fbff808) + 68 at main.m:15
frame #12: 0x00007fff8bea05ad libdyld.dylib`start + 1
frame #13: 0x00007fff8bea05ad libdyld.dylib`start + 1
Debugowanie SIGABRT i EXC_BAD_INSTRUCTION ulega awarii
SIGABRT
lub EXC_BAD_INSTRUCTION zwykle oznacza, że aplikacja celowo uległa awarii, ponieważ niektóre testy zakończyły się niepowodzeniem. Powinny one zalogować komunikat do konsoli debugera z dodatkowymi informacjami; sprawdź tam, aby uzyskać więcej informacji.
Wiele SIGABRT
jest spowodowanych nieprzechwyconymi wyjątkami Celu C. Istnieje wiele powodów, dla których można zgłaszać wyjątki i zawsze rejestrują one wiele przydatnych informacji w konsoli.
-
NSInvalidArgumentException
, co oznacza, że aplikacja przekazała nieprawidłowy argument do metody -
NSRangeException
, co oznacza, że aplikacja próbowała uzyskać dostęp do indeksu poza zakresem obiektu, takiego jakNSArray
lubNSString
-
NSInternalInconsistencyException
oznacza, że obiekt wykrył, że był w nieoczekiwanym stanie. -
NSUnknownKeyException
zwykle oznacza, że masz złe połączenie w XIB. Wypróbuj niektóre odpowiedzi na to pytanie .
Debugowanie EXC_BAD_ACCESS
EXC_BAD_ACCESS
oznacza, że proces próbował uzyskać dostęp do pamięci w niepoprawny sposób, na przykład wyrejestrowanie wskaźnika NULL
lub zapis do pamięci tylko do odczytu. Jest to najtrudniejszy rodzaj awarii do debugowania, ponieważ zwykle nie zawiera komunikatu o błędzie, a niektóre awarie mogą być bardzo trudne do odtworzenia i / lub występują w kodzie całkowicie niezwiązanym z problemem. Ten błąd występuje bardzo rzadko w Swift, ale jeśli wystąpi, często można uzyskać łatwiejsze do debugowania awarie poprzez zmniejszenie optymalizacji kompilatora.
Większość błędów EXC_BAD_ACCESS
jest spowodowana próbą wyłuskiwania wskaźnika NULL
. W takim przypadku adres wymieniony w czerwonej strzałce będzie zwykle liczbą szesnastkową niższą niż normalny adres pamięci, często 0x0
. Ustaw punkty przerwania w debuggerze lub dodaj okazjonalne instrukcje printf
/ NSLog
, aby dowiedzieć się, dlaczego ten wskaźnik ma NULL
.
EXC_BAD_ACCESS
który występuje mniej niezawodnie lub nie ma żadnego sensu, może być wynikiem problemu z zarządzaniem pamięcią. Typowe problemy, które mogą to powodować:
- Używanie pamięci, która została zwolniona
- Próba zapisu poza końcem tablicy C lub innego rodzaju bufora
- Korzystanie ze wskaźnika, który nie został zainicjowany
W sekcji Diagnostyka edytora schematów Xcode zawiera kilka przydatnych narzędzi ułatwiających debugowanie problemów z pamięcią:
Address Sanitizer dodaje wiele kontroli, które zatrzymają aplikację za każdym razem, gdy wystąpią problemy z pamięcią i dostarczą pomocnego komunikatu o błędzie szczegółowo opisującego, co się stało. Zombie Objects wykrywa problemy z cofniętymi obiektami Objective-C, ale nie powinieneś mieć tego typu problemów z włączonym automatycznym zliczaniem odniesień.