Wyjątek debugowania rzucany w Objective C i XCode

Jestem wieloletnim programistą Microsoftu i jestem nowy w rozwoju iPhone ' a za pomocą XCode. Tak więc czytam książkę i przeglądam przykłady, próbując nauczyć się pisać aplikację na iPhone 'a za pomocą Objective-C. jak dotąd wszystko było dobre, jednak raz na jakiś czas natrafiam na ogólny komunikat" objc_exception_throw " w czasie wykonywania. Kiedy tak się dzieje, źródło tego wyjątku jest bardzo trudne do znalezienia. Po próbach i błędach znalazłem odpowiedź. Jeden z parametrów został błędnie zapisany.

Jak widać poniżej, źle napisałem parametr 'otherButtonTitles', pomijając drugie' t ' w przycisku.

UIAlertView *alert = [[UIAlertView alloc] 
                      initWithTitle:@"Date and Time Selected" 
                      message:message 
                      delegate:nil
                      cancelButtonTitle:@"Cancel"
                      otherButonTitles:nil];
Powodem, dla którego Zajęło mi to trochę czasu, jest to, że kod został pomyślnie zbudowany. Czy to normalne zachowanie dla kompilatora Objective-C? Jestem przyzwyczajony do niepowodzenia kompilacji w kompilatorze. NET, gdy popełniam powszechny błąd składni, taki jak ten. Czy istnieje ustawienie kompilatora, które mogę zmienić, aby built nie powiódł się, gdy popełniam te błędy?
Author: AlBlue, 2009-04-03

5 answers

Przede wszystkim otwórz ~/.gdbinit (to plik o nazwie .gdbinit w Twoim katalogu domowym-tak, zaczyna się od kropki) i umieść w nim to:

fb -[NSException raise]
fb objc_exception_throw
fb malloc_error_break

To zainicjalizuje GDB trzema domyślnymi punktami przerwania, gdy one wystąpią, GDB zatrzyma Twoją aplikację i wyświetli ślad stosu. Jest to bardzo dobrze zintegrowane z Xcode, więc będziesz w stanie ładnie przejść przez kod, klikając stos elementów śladowych, jak tylko wystąpi wyjątek gdzieś lub malloc nie powiedzie.

Wtedy, otwórz panel Get Info w swoim projekcie (lub wybierz swój projekt (górny element w Groups & Files) i naciśnij cmd-i), przejdź do zakładki Build i ustaw Base SDK na Device - iPhone OS [someversion]. Przewiń do dołu i znajdź sekcję GCC 4.0 - Warnings. Tam; włącz tyle ostrzeżeń, ile ci się podoba, ale pamiętaj, aby włączyć Treat Warnings as Errors (jest to odpowiednik GCC_TREAT_WARNINGS_AS_ERRORS). Osobiście mam to ustawione na to:

GCC Warning Build Settings http://lhunath.lyndir.com/stuff/gcc_warnings.png

Powinieneś otrzymywać ostrzeżenia kompilatora dla większości rzeczy, które możesz zrobić źle w kodzie i kompilator nie pozwoli Ci uruchomić kodu, dopóki ich nie naprawisz. Gdy rzeczy miną nos kompilatora, powinieneś być w stanie łatwo znaleźć problem z łamaniem GDB w dogodnym miejscu.

Powinieneś również zajrzeć do NSZombie*. Są to Zmienne środowiskowe, które są bardzo przydatne do wczesnego przerwania złej alokacji pamięci lub sytuacje dostępu. Na przykład; wih NSZombieEnabled nic tak naprawdę nie zostanie wydane; na dealloc zostanie nadpisane _NSZombie i jeśli spróbujesz ponownie uzyskać dostęp do tej deallocowanej pamięci (dereferując deallocowany wskaźnik), otrzymasz coś do złamania w GDB, zamiast połączenia przebiegającego normalnie, tylko emitowanego na losowych danych (co oczywiście nie jest tym, czego chciałeś). Aby uzyskać więcej informacji na ten temat, zobacz http://www.cocoadev.com/index.pl?NSZombieEnabled .

 25
Author: lhunath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-03 05:38:30

Zawsze używaj ustawienia -Werror GCC (GCC_TREAT_WARNINGS_AS_ERRORS = YES). Nigdy nie powinieneś mieć ostrzeżeń w kodzie i jest to przykład, w którym ostrzeżenie jest krytycznym błędem.

Również, jeśli otrzymasz objc_exception_throw, przełącz się na konsolę (Command-shift-R) i poszukaj pierwszego "niskiego" adresu numeru.

2009-04-01 13:25:43.385 CrashExample[41720:20b] Stack: (
    2528013804,
    2478503148,
    2528036920,
    2528053460,
    2358032430,
    11076,
    11880,
    816174880,
    345098340,
    145973440,
    816174880,
)

W tym przypadku będzie to "11076". Więc wpisz w konsoli:

info line *11076

To powie Ci linię w kodzie, w której został wyrzucony wyjątek.

 9
Author: Matt Gallagher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-02 23:30:00

Błędne parametry powinny zazwyczaj skutkować" Warning: such-and-such object does not response to selector x " na Żółto w danej linii. Uważam, że jest to domyślnie włączone, ponieważ nie musiałem zmieniać żadnych ustawień kompilatora, aby je zobaczyć.

Również, gdy napotkam nieobciążony wyjątek, czasami korzystne jest wrzucenie do konsoli gdb (powinno pojawić się podczas uruchamiania aplikacji) i wpisanie następującej pozycji, aby uzyskać ścieżki zwrotne dla wszystkich wątków:

T a a bt

 8
Author: drewh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-02 21:17:02

To, co zrobiłeś, nie jest błędem w czasie kompilacji, ponieważ Runtime Objective - C sprawdza, czy obiekt może odpowiedzieć na wiadomość, którą do niego wysyłasz.

Zalecam dodanie tego ustawienia budowania do celu lub projektu:

GCC_TREAT_WARNINGS_AS_ERRORS = YES
 2
Author: Chris Lundie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-02 22:14:07

Powodem, dla którego nie jest to błąd kompilacji, jest to, że całkowicie poprawne jest wysyłanie wiadomości nieznanej w czasie kompilacji do dowolnego obiektu (i każdy obiekt może być skonfigurowany tak, aby obsługiwał wiadomości dynamicznie). Wszystkie wywołania metod są tak naprawdę wiadomościami wysyłanymi do obiektów.

Ogólnie rzecz biorąc, jeśli widzisz jakieś ostrzeżenia, powinieneś je adresować, ponieważ w większości przypadków mogą one prowadzić do problemów(jak widziałeś). Mylącym aspektem jest tutaj to, że jeśli skompilujesz plik raz i ma on tylko ostrzeżenia, jeśli kompilujesz inne klasy bez wprowadzania zmian do klasy, która ma ostrzeżenia, ostrzeżenie nie pojawi się w komunikatach kompilatora. Więc od czasu do czasu możesz chcieć "wyczyścić wszystkie cele" i zbudować ponownie, aby upewnić się, że nie przegapisz żadnych ostrzeżeń.

 1
Author: Kendall Helmstetter Gelner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-02 21:31:35