2009-04-02 4 views
10

Ich bin ein langjähriger Microsoft-Entwickler und ich bin neu in iPhone-Entwicklung mit XCode. Also lese ich ein Buch und gehe Beispiele durch, um mir selbst beizubringen, wie man eine iPhone-Anwendung mit Objective-C schreibt. Bisher war alles gut, aber ab und zu liefere ich zur Laufzeit auf die generische 'objc_exception_throw'-Meldung. Wenn dies geschieht, ist die Quelle dieser Ausnahme sehr schwer zu finden. Nach etwas Versuch und Irrtum fand ich meine Antwort. Einer der Parameter wurde falsch geschrieben.Debugging-Ausnahme in Objective C und XCode

Wie Sie unten sehen können, habe ich den Parameter 'otherButtonTitles' falsch geschrieben, indem ich die zweite Taste 't' ausgelassen habe.

UIAlertView *alert = [[UIAlertView alloc] 
         initWithTitle:@"Date and Time Selected" 
         message:message 
         delegate:nil 
         cancelButtonTitle:@"Cancel" 
         otherButonTitles:nil]; 

Der Grund, warum ich mich Zeit nahm zu finden ist, dass der Code erfolgreich erstellt wurde. Ist das für den Objective-C-Compiler normal? Ich bin es gewohnt, dass der Build im .NET Compiler fehlschlägt, wenn ich einen allgemeinen Syntaxfehler wie diesen mache. Gibt es eine Compiler-Einstellung, die ich ändern kann, um das Build fehlschlagen zu lassen, wenn ich diese Fehler mache?

+1

Jemand mit mehr rep als ich sollte den Titel zu etwas wie "Debuggen und Verhindern" objc_exception_throw "" bearbeiten. –

Antwort

25

In erster Linie offen ~/.gdbinit (das ist die Datei .gdbinit in Ihrem Home-Verzeichnis genannt - ja, mit einem Punkt beginnt) und setzt diese in ihm:

fb -[NSException raise] 
fb objc_exception_throw 
fb malloc_error_break 

Das wird GDB initialisieren mit drei Standard-Stützpunkten Wenn sie auftreten, wird GDB Ihre Anwendung anhalten und Ihnen die Stack-Trace anzeigen. Dies ist sehr gut in Xcode integriert, so dass Sie in der Lage sein werden, Ihren Code durch Klicken auf Stack-Trace-Elemente zu durchlaufen, sobald eine Ausnahme auftritt oder ein Malloc ausfällt.

Öffnen Sie dann die Get Info Panel an Ihrem Projekt (oder wählen Sie Ihr Projekt (oben Artikel im Groups & Files) und traf cmd-i), gehen Sie auf die Registerkarte Build und setzen Base SDK-Device - iPhone OS [someversion] Ihres Projekts. Blättern Sie den ganzen Weg nach unten und finden Sie den GCC 4.0 - Warnings Abschnitt. Dort; schalten Sie so viele Warnungen ein, wie Sie sich wohl fühlen, aber stellen Sie sicher, dass Sie Treat Warnings as Errors einschalten (dies entspricht GCC_TREAT_WARNINGS_AS_ERRORS). Persönlich habe ich es so weit gesetzt:

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

Sie jetzt immer Compiler-Warnungen für die meisten Dinge sollten Sie in Code falsch machen kann und der Compiler wird nicht zulassen, Sie den Code ausführen, bis Sie sie reparieren. Wenn die Dinge an der Nase des Compilers vorbeikommen, sollten Sie das Problem leicht finden können, wenn GDB an einer geeigneten Stelle bricht.

Sie sollten auch in NSZombie* suchen. Dies sind Umgebungsvariablen, die sehr nützlich sind, um bei schlechter Speicherzuordnung oder Zugriffssituationen frühzeitig zu brechen. Zum Beispiel; mit NSZombieEnabled wird nichts wirklich veröffentlicht werden; Beim Dealloc wird es mit _NSZombie überschrieben und sollten Sie versuchen, erneut auf diesen freigegebenen Speicher zuzugreifen (Dereferenzierung eines dealloced Pointers), erhalten Sie etwas in GDB, statt dass der Call wie normal ausgeführt wird und nur zufällig ausgegeben wird Daten (was natürlich nicht das ist, was Sie wollten). Weitere Informationen hierzu finden Sie unter http://www.cocoadev.com/index.pl?NSZombieEnabled.

+0

HINWEIS: Damit der Abschnitt "GCC 4.0 Warnings" in Ihren Einstellungen angezeigt wird (wie oben gezeigt), müssen das Base SDK und das Active SDK auf das Gerät und nicht auf den Simulator eingestellt sein. – rtemp

+0

Wenn Sie "Warnmeldungen als Fehler behandeln" aktivieren, sehen Sie immer noch die Warnungen wie zuvor, aber Sie erhalten einen etwas irreführenden Fehler "Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.0 ist fehlgeschlagen Ausgangscode 1 ". Dieser Fehler verschwindet, wenn alle Warnungen gelöscht sind. – rtemp

8

Falsch geschriebene Parameter sollten in der Regel zu einer "Warnung: Das-und-so-Objekt reagiert nicht auf Selektor x" in Gelb bei der betreffenden Zeile führen. Ich glaube, das ist standardmäßig aktiviert, da ich keine Compiler-Einstellungen ändern musste, um diese zu sehen.

Auch, wenn ich eine abgefangene Ausnahme begegnen, ist es manchmal vorteilhaft in die GDB-Konsole fallen (kommen sollten, wenn Sie Ihre Anwendung ausführen) und die folgende Typ Backtraces für alle Threads zu bekommen:

taa bt

+0

"taa bt" ist eine Abkürzung für "thread apply all backtrace" und druckt einfach ein Backtrace für alle Threads –

1

Der Grund dafür, dass es sich nicht um einen Kompilierungsfehler handelt, ist, dass es absolut zulässig ist, eine Nachricht, die bei der Kompilierung nicht bekannt ist, an ein beliebiges Objekt zu senden (und jedes Objekt kann auch dynamisch für Nachrichten konfiguriert werden). Alle Methodenaufrufe sind wirklich Nachrichten, die an Objekte gesendet werden.

Im Allgemeinen, wenn Sie Warnungen sehen, sollten Sie sie ansprechen, da sie in den meisten Fällen zu Problemen führen können (wie Sie gesehen haben). Der irreführende Aspekt ist hier, dass, wenn Sie eine Datei einmal kompilieren und nur Warnungen haben, wenn Sie andere Klassen kompilieren, ohne Änderungen an der Klasse vorzunehmen, die Warnungen hat, wird die Warnung in den Compiler-Nachrichten nicht angezeigt. Daher solltest du hin und wieder alle Ziele säubern und erneut bauen, um sicherzustellen, dass du keine Warnungen verpasst hast.

2

Was Sie getan haben, ist kein Fehler bei der Kompilierung, da die Objective-C-Laufzeit zur Laufzeit prüft, ob ein Objekt auf die Nachricht antworten kann, die Sie an es senden.

Ich empfehle das Hinzufügen dieses Build zu Ihrem Ziel oder Projekt einstellen:

GCC_TREAT_WARNINGS_AS_ERRORS = YES 
9

Verwenden Sie immer die -Werror GCC-Einstellung (GCC_TREAT_WARNINGS_AS_ERRORS = YES). Sie sollten niemals Warnungen in Ihrem Code haben und dies ist ein Beispiel, bei dem die Warnung ein kritischer Fehler ist.

Wenn Sie eine objc_exception_throw bekommen, wechseln Sie zur Konsole (Command-shift-R) und suchen Sie nach der ersten "low" Nummer Adresse.

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

In diesem Fall wäre es "11076". Geben Sie die Konsole ein:

info line *11076 

Das wird Ihnen die Zeile in Ihrem Code sagen, wo die Ausnahme ausgelöst wurde.

+0

Das ist ein guter Tipp - eine weitere Sache ist, einen globalen Haltepunkt auf "objc_exception_throw" zu setzen, der automatisch bricht, wenn Ihr Code tut etwas, das eine Ausnahme auslöst. –