Warum wird Clang durch @try {} in einem Block ohne Rückgabeanweisung verwechselt?

8

Unter normalen Bedingungen, wenn ein Block deklariert wird, einen Wert zurückzugeben, aber keine return -Anweisung tatsächlich im Block erscheint, kann Clang sie nicht mit einem Fehler (eines fehlenden Rückgabewerts) kompilieren.

Dies bricht jedoch, wenn dieser Block @try{} @catch(...){} oder @try{} @finally{} enthält.

Weiß jemand warum?

Wie ich das gefunden habe, wenn ich @weakify() und @strongify() in RACExtScope in ReactiveCocoa benutzte, vergaß ich in einem Block ein Signal zurückzusenden. Aber der Compiler hat mich nicht gewarnt und ist zur Laufzeit abgestürzt, was mich dazu gebracht hat, den Code zu bearbeiten und zu finden, dass dies den Fehler verursacht. Jede Erklärung würde sehr geschätzt werden, ich weiß ehrlich nicht, warum das passieren würde, danke!

Ich habe auch einen Text erstellt, falls jemand einen Kommentar / Vorschlag hatte: Ссылка

%Vor%     
czechboy 28.04.2014, 00:46
quelle

1 Antwort

4

Die Blockspezifikation von Clang erwähnt kurz den Kontrollfluss in einem Block. Ich habe es hier reproduziert (Betonung meiner)

  

Die zusammengesetzte Anweisung eines Blocks wird ähnlich wie ein Funktionskörper behandelt   in Bezug auf den Kontrollfluss in diesem Goto, Pause, und weiter nicht   Entkomme dem Block. Ausnahmen werden normal behandelt, wenn sie ausgelöst werden   Sie stapeln Frames, bis eine catch-Klausel gefunden wird.

Wenn man etwas weiter liest, bekommt man wirklich das Gefühl, dass Ausnahmen in Objective-C geradezu seltsam sind. Von der Abschnitt über Ausnahmen

  

Die standardmäßige Cocoa-Konvention ist, dass Ausnahmen Programmierer signalisieren   Fehler und sollen nicht von wiederhergestellt werden. Code erstellen   Exceptions-safe würde standardmäßig schwerwiegende Laufzeit und Code-Größe auferlegen   Strafen für Code, der normalerweise nicht wirklich wichtig ist   Ausnahmen Sicherheit. Aus diesem Grund leckt der ARC-generierte Code standardmäßig   Ausnahmen, das ist gut, wenn der Prozess sein wird   sofort beendet sowieso. Programme, die sich um die Wiederherstellung kümmern   Aus Ausnahmen sollte die Option aktivieren.

Aus dem Obigen kann vernünftigerweise abgeleitet werden, dass die ObjC-Exceptions-Spezifikation so zerbrechlich oder formbar ist, dass nicht einmal die Compiler-Autoren stabilen Code dagegen garantieren können. Daher haben sie einfach alle vernünftigen Beendigungs-Checks in @ try- @ catch deaktiviert angetroffen.

Dies kann auch in dem Code gesehen werden, der von Clang mit und ohne Try-Catch generiert wurde. Zuerst ohne

%Vor%

Das ist ziemlich einfach x86, das einen neuen Stapelrahmen verschiebt, 0 (Null) in das Rückgabe-Register bewegt und dann zurückkehrt. Jetzt mit dem try-catch-Block:

%Vor%

Bemerken Sie neben dem komplizierteren Funktionsproblem das Fehlen eines richtigen ret . Die Funktion hat noch zwei Ausgangspunkte,

%Vor%

und

%Vor%

Die erste ist eine relativ neue Eigenschaft der Sprache, bei der in der hinteren Aufrufposition -autoreleases zugunsten des Zeichnens auf thread-lokale Variablen weggelassen werden kann, indem der davor liegende Code untersucht wird. Die zweite beginnt mit der sofortigen Beendigung des Prozesses und springt in den C ++ - Ausnahmebehandlungsmechanismus. Das bedeutet, dass die Funktion tatsächlich über die erforderlichen Ausstiegspunkte verfügt, damit CLANG sich nicht über fehlende Rückmeldungen beschweren kann. Unglücklicherweise bedeutet das auch, dass CLANGs Verzicht auf den ObjC-Ausnahmemechanismus potenziell Müll melden kann, wie Sie gesehen haben. Dies ist einer der Gründe, warum EXTScope zur Verwendung der @autoreleasepool -Direktive gewechselt hat, um dieses Siegel zu essen.

>     
CodaFi 01.05.2014, 02:51
quelle