Inkonsistente Objektfreigabe mit ARC?

8

Ich habe mit Speicherdeaktivierungs-Dingen in einer einfachen Befehlszeilen-App für Mac OSX 10.7 gespielt, die mit Xcode Version 4.2.1 mit aktiviertem ARC und den Standard-Build-Einstellungen erstellt wurde. Ich kann nicht erklären, was ich von ARC verstehe. Ich hoffe, dass jemand erklären kann, was hier vor sich geht.

Als Erstes bekomme ich im folgenden Code das erwartete Verhalten (bitte beachten Sie, dass die Ausgabe von NLog () im Kommentar nach der entsprechenden Anweisung angegeben wird)

%Vor%

Im obigen Beispiel, direkt nachdem weakRef zugewiesen wurde, hat die NSObject-Instanz zwei starke Zeiger darauf und daher eine Retain-Zahl von 2. Nach dem Nullstellen von objPtr1 gibt es immer noch einen Haltezeiger für die Instanz, so dass sie immer noch im Speicher ist antwortet auf die Beschreibung Nachricht. Nach dem Nullen von objPtr2 gibt es keine starken Zeiger auf das Objekt und es wird freigegeben (ich nehme an, dass es ist, da weakRef auf Null gesetzt wurde). So weit, so gut.

Nun, der gleiche Code mit einer kleinen Änderung:

%Vor%

Ich habe erwartet, dass weakRef zu einem ungeeigneten Zeiger wird, der eine Nachricht sendet, durch die das Programm in der dritten NSLog () -Anweisung zum Absturz gebracht wird, aber es scheint, dass die Objektinstanz noch lebt und gut ist.

Eine andere Sache, die ich seltsam finde:

%Vor%

Dieser letzte Code ist wie der erste (mit dem genullten __weak Zeiger); Der einzige Unterschied besteht darin, dass die Beschreibungsnachricht in jedem der drei NSLog () - Aufrufe über weakRef an das Objekt gesendet wurde. Aber dieses Mal wird das Objekt nicht freigegeben, selbst nachdem die beiden starken Referenzen entfernt wurden (da es immer noch auf Nachrichten durch weakRef reagiert).

Also, was ist hier los?

    
Aky 07.02.2012, 08:32
quelle

2 Antworten

3

Wenn Sie von A. R. C. produzierten Code zerlegen, wird jeder Zugriff auf eine schwache Variable in einen Aufruf dieser Funktion eingeschlossen:

%Vor%

Dies prüft, ob das Objekt bereits freigegeben wurde, und wenn nicht, behält es es und gibt es automatisch wieder, um zusätzliche Sicherheit vor vorzeitigem Deallocs zu gewährleisten.

In Ihrem dritten Beispiel führen die frühen Aufrufe der Methode auf weakRef dazu, dass die Retain-Anzahl erhöht wird, so dass Ihre Zeiger nicht gelöscht werden müssen.

    
grahamparks 12.02.2012 12:54
quelle
1

Das scheint seltsam. Sie haben Recht (in Ihren Kommentaren) über das 2. Bit des Codes, nur weil der Speicher noch nicht wiederverwendet wurde. Aber das dritte Bit Code ist Fremder. Hier ist ein vereinfachter Testfall, der dieses seltsame Problem zeigt:

%Vor%

Wenn diese Zeile auskommentiert ist, lautet die Ausgabe:

%Vor%

Wenn die Zeile unkommentiert ist, lautet die Ausgabe:

%Vor%

Das erscheint mir zutiefst merkwürdig und sieht für mich wie ein Käfer aus. Ich weiß eigentlich nicht, was die Antwort ist, aber ich dachte, ich würde dies als eine Antwort veröffentlichen, um den Ball ins Rollen zu bringen, um herauszufinden, was los ist.

Aktualisierung:

Wenn Sie dies bei O0 erstellen, scheint weakRef nur auf Null gesetzt zu sein, wenn no Aufrufe von foo sind. Ein einzelner Aufruf von foo bedeutet, dass es nicht auf Null gesetzt wird.

    
mattjgalloway 12.02.2012 00:43
quelle