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):
Es wäre eine Antwort wert, die zeigt, wie ARC unter der Haube funktioniert ( objc_release
, objc_retainAutoreleasedReturnValue
, etc.).
Vielen Dank im Voraus.
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.
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.
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.
Tags und Links objective-c llvm-clang automatic-ref-counting