retainCount liefert INT_MAX bei NSNumber?!?

  • retainCount liefert INT_MAX bei NSNumber?!?

    Heyhey,
    ich habe gerade angefangen mich mit Objektive C zu beschäftigen, da ich in die App-Programmierung einsteigen möchte.
    (An sich bin ich eigentlich in der Java-Programmierung heimisch ;) )

    Nun, bin gerade bei der Speicherverwaltung und wollte eigene kleine Tests machen:

    Quellcode

    1. #import <Foundation/Foundation.h>
    2. int main(int argc, const char * argv[])
    3. {
    4. NSAutoreleasePool* pool =[[NSAutoreleasePool alloc]init];
    5. NSNumber* myInt =[NSNumber numberWithInteger:100]; //IntegerObjekt anlegen
    6. NSLog(@"myInt retain count = %lx", //retainCount Ausgabe für IntegerObj
    7. ((unsigned long)[myInt retainCount]));
    8. [myInt retain]; //retainCount erhöhen
    9. NSLog(@"myInt retain count = %lx", //retainCount Ausgabe für IntegerObj
    10. ((unsigned long)[myInt retainCount]));
    11. [pool drain];
    12. return 0;
    13. }
    Alles anzeigen



    Erwartet hätte ich die Ausgabe:

    myInt retain count = 1
    myInt retain count = 2


    Jedoch kam:

    myInt retain count = 7fffffffffffffff

    myInt retain count = 7fffffffffffffff

    ...also der Hexwert für ein INT_MAX!


    Kann mir das einer erklären?
    Mir ist bekannt, dass konstanten Strings diese Ausgabe erscheint,
    da sie im Speicher anders zugewiesen werden und somit keine Referenzzähler besitzen.
    Aber bei einem NSNumber ist dies doch nicht der fall.

    Leider nichts in der Suchfunktion gefunden!

    Ich bitte daher um Hilfe.
    Vielen Dank!
  • Freeandstyle schrieb:

    Kann mir das einer erklären?

    Es gibt Klassen, bei denen einige Objekte nur so tun, als lägen sie im Heap. Tatsächlich sind das Konstanten, die man weder allozieren noch freigeben kann. Die üblichen Verdächtigen hier sind NSString, NSNumber und andere. Im Allgemeinen ist der Retaincount eine hübsche Zahl, die man sich mal anschauen kann. Du solltest sie aber ganz schnell wieder vergessen. Diese Schlampe betrügt Dich, wo sie nur kann.

    Oder anders ausgedrückt: Der Retaincount ist ein Implementierungsdetail, der Dich nichts angeht.
    „Meine Komplikation hatte eine Komplikation.“
  • Hallo macmoonshine,

    Danke für deine schnelle Antwort.
    Nein nein, ich hatte nicht vor mit retainCount zu arbeiten. Wollte mir nur die Funktionsweise des Zählers klar machen ;)

    Was mich halt wundert:
    Ich hatte dieses Testprogramm aus Dem Buch: Obective-C 2.0 abgeschaut.
    Daran hatten sie den Referenzzähler erklärt.

    Im Buch wurde auch NSNumber verwendet, deswegen war ich erstaunt, dass sich NSNumber wie NSString verhält.

    Bin deswegen jetzt leicht verwirrt.

    Muss bzw. kann ich diese Klassenobjekte garnicht selber frei geben?

    Im Buch steht:

    Aufpassen bei NSMutableArray!

    myInt=[myArr ObjectAtIndex:0];
    ...
    [myArr removeObjectAtIndex:0];

    hier würde der Referenzzähler also auf 0 gesetzt obwohl noch eine Referenz existiert, nämlich: myInt.

    ...ist dies also doch nicht bei NSNumber der Fall?

    Und warum steht so ein Quelltest im buch der garnicht richtig funktioniert?...hat sich evtl die Implementierung von Foundation geändert?
    Das Buch ist von 2009

    Danke
  • 1. Du behandelst das bitte wie jede Instanz. Das ist ein Implementationsdetail.

    2. Der Hinweis auf Arrays ist so eng Quatsch. Das geht mit jeder anderen Instanz jedes anderen Entitätstypen auch. Der "Fehler" liegt darin, dass man sich in dem Beispiel ein retain/release-Paar im Kopf wegoptimiert hat. Dagegen ist auch nichts zu sagen. Man muss es bloß im Kopf behalten.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Freeandstyle schrieb:

    hier würde der Referenzzähler also auf 0 gesetzt obwohl noch eine Referenz existiert, nämlich: myInt.

    Bei manuellem Referenzenzählen ist myInt kein Eigentümer des Objekts. Ich kenne das Buch nicht, aber der Quelltext ist wohl eher als Beispiel für einen falschen Umgang mit Referenzen gemeint.

    Freeandstyle schrieb:

    ...ist dies also doch nicht bei NSNumber der Fall?

    Nein, es kann bei bestimmten NSNumber-Objekten nicht der Fall sein. Wenn der Wert des NSNumber-Objekts groß genug ist und erst zur Laufzeit feststeht, erhältst Du ein dynamisch allokiertes Objekt.

    Im Gegensatz zu einem Java-Konstruktor liefert eine Objective-C alloc-init-Kette nicht immer ein Objekt mit genau der Klasse in der Anweisung (NSNumber ist beispielsweise ein Class-Cluster). Objective-C ist da sehr viel flexibler.
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Freeandstyle schrieb:

    hier würde der Referenzzähler also auf 0 gesetzt obwohl noch eine Referenz existiert, nämlich: myInt.

    Bei manuellem Referenzenzählen ist myInt kein Eigentümer des Objekts. Ich kenne das Buch nicht, aber der Quelltext ist wohl eher als Beispiel für einen falschen Umgang mit Referenzen gemeint.

    Freeandstyle schrieb:

    ...ist dies also doch nicht bei NSNumber der Fall?

    Nein, es kann bei bestimmten NSNumber-Objekten nicht der Fall sein. Wenn der Wert des NSNumber-Objekts groß genug ist und erst zur Laufzeit feststeht, erhältst Du ein dynamisch allokiertes Objekt.

    Im Gegensatz zu einem Java-Konstruktor liefert eine Objective-C alloc-init-Kette nicht immer ein Objekt mit genau der Klasse in der Anweisung (NSNumber ist beispielsweise ein Class-Cluster). Objective-C ist da sehr viel flexibler.

    Es kann sogar ein Objekt derselben Klasse sein. Entscheidend ist, dass eine Erzeugermethode nicht zwingend ein neues Objekt erzeugt, sondern insbesondere den RC eines bestehende verändert und dieses dann zurückliefert.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    Es kann sogar ein Objekt derselben Klasse sein.

    Ja, natürlich.

    Amin Negm-Awad schrieb:

    Entscheidend ist, dass eine Erzeugermethode nicht zwingend ein neues Objekt erzeugt, sondern insbesondere den RC eines bestehende verändert und dieses dann zurückliefert.

    Wenn das zurückgelieferte Objekt aber eine Konstante mit konstantem Retaincount ist, fasst sie den Retaincount aber nicht an. ;)
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Amin Negm-Awad schrieb:

    Es kann sogar ein Objekt derselben Klasse sein.

    Ja, natürlich.

    Amin Negm-Awad schrieb:

    Entscheidend ist, dass eine Erzeugermethode nicht zwingend ein neues Objekt erzeugt, sondern insbesondere den RC eines bestehende verändert und dieses dann zurückliefert.

    Wenn das zurückgelieferte Objekt aber eine Konstante mit konstantem Retaincount ist, fasst sie den Retaincount aber nicht an. ;)

    Wenn, deshalb schrieb ich ja auch "insbesondere".

    Man kann aber beim Twintonign einfach ein -retain/-autorelease senden, wie es NSNumber lange Zeit machte und ich übrigens immer noch.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?