Objective-C Namenskonventionen mit ARC und möglichen Einschränkungen

8

Ich habe Erfahrung mit reiner ARC-Codierung. Als Compiler-Feature berücksichtigt es die Objctive-C-Methodenfamilie, die Rechte behält / freigibt, wenn sie benötigt werden.

Alle Methoden, die mit alloc , mutableCopy , copy und new beginnen, erstellen ein neues Objekt. Sie erhöhen die Retain-Anzahl. Als Konsequenz wird ARC jeden Zeiger (und folglich das damit verbundene Objekt) freigeben, wenn ich ihn nicht mehr brauche.

Ich denke, dass Probleme auftreten können, wenn ich Methoden schreibe, die nicht den Namenskonventionen folgen. Wenn ich zum Beispiel eine Methode wie newCustomer schreibe, die in einer ersten Version ein automatisch freigegebenes Objekt zurückgibt, während dies in einer zweiten Version nicht der Fall ist, was könnte passieren?

Insbesondere sind meine Fragen die folgenden (sie gehören zu derselben Argumentation):

  • Was passiert, wenn der aufrufende und der aufgerufene Code beide mit ARC kompiliert werden?
  • (a) Was passiert, wenn der aufrufende Code mit ARC kompiliert wird, während der aufgerufene mit nicht-ARC kompiliert wird?
  • (b) Was passiert, wenn der aufrufende Code mit Nicht-ARC kompiliert wird, während der Aufruf mit ARC kompiliert wird?

Es wäre eine Antwort wert, die zeigt, wie ARC unter der Haube funktioniert ( objc_release , objc_retainAutoreleasedReturnValue , etc.).

Vielen Dank im Voraus.

    
Lorenzo B 01.04.2013, 16:28
quelle

2 Antworten

12

Eine Methode namens newCustomer würde in die new Methodenfamilie fallen und ist somit implizit so gekennzeichnet, dass ein beibehaltenes Objekt zurückgegeben wird. Wenn sowohl der aufrufende als auch der aufgerufene Code mit ARC kompiliert wird, gleicht ARC den zusätzlichen Retain mit einer Freigabe im Aufrufer aus:

  

Wenn ARC von einer solchen Funktion oder Methode zurückkehrt, behält ARC den Wert bei   zum Zeitpunkt der Auswertung der Rücksendung, bevor Sie alle verlassen   lokale Bereiche.

     

Wenn Sie von einer solchen Funktion oder Methode ein Rückgabeergebnis erhalten, ARC   gibt den Wert am Ende des enthaltenen vollständigen Ausdrucks frei   innerhalb, vorbehaltlich der üblichen Optimierungen für lokale Werte.

Quelle

Wenn newCustomer mit manuellem Referenzzählen implementiert wird und die Namenskonvention verletzt (d. h. ein beibehaltenes Objekt nicht zurückgibt), kann der Aufrufer je nach den Umständen entweder die Freigabe oder die Freigabe freigeben.

Wenn der Aufrufer ARC verwendet, wird das von newCustomer zurückgegebene Objekt überveröffentlicht - was wahrscheinlich zum Absturz des Programms führt. Dies liegt daran, dass der aufrufende Code in der zweiten Hälfte des obigen Prozesses teilnehmen wird, ohne dass zuvor eine entsprechende Zurückhaltung durchgeführt wurde.

Wenn der aufrufende Code nicht mit ARC kompiliert wird, sondern der aufgerufene Code (und somit die Rückgabe eines beibehaltenen Objekts korrekt implementiert wird), hängt das Verhalten davon ab, dass der Programmierer den Namenskonventionen folgt. Wenn sie den zurückgegebenen Wert freigeben, wird die Referenzzählung des Objekts korrekt verwaltet. Wenn der Programmierer jedoch glaubt, dass die Methode new... gegen die Namenskonvention verstößt und eine Freigabe nicht manuell in den aufrufenden Code einfügt, wird das zurückgegebene Objekt undicht.

Alles in allem ist es, wie Martin R. in den Kommentaren betont, entscheidend, ob die Namenskonventionen in jeder Umgebung eingehalten werden, einschließlich der manuellen Referenzzählung.

    
Carl Veazey 01.04.2013, 16:53
quelle
2

Genau wie jede andere Sprache wandern Sie, wenn Sie einige Grundannahmen der Sprache verletzen, in das Gebiet des undefinierten Verhaltens ein. Irgendwann in der Zukunft könnte Apple die Interna von -new... referenzieren. Es ist Sache von Apple, dafür zu sorgen, dass der Code, der der erwarteten Verwendung entspricht, funktioniert, dies jedoch nicht für nicht konforme Zwecke.

Wenn Sie wissen möchten, wie das tatsächliche Verhalten für eine bestimmte Version eines Compilers aussieht, der auf einem bestimmten System ausgeführt wird, müssen Sie es testen. Gehen Sie nicht davon aus, dass das Verhalten für andere Compiler oder Versionen der Laufzeit identisch ist.

Am Ende ist undefiniertes Verhalten ein undefiniertes Verhalten. Wenn Sie Code erstellen, der darauf basiert, werden Sie möglicherweise von einem subtilen und schwer zu diagnostizierenden Defekt betroffen sein.

    
Jeffery Thomas 01.04.2013 16:57
quelle