[myObject release]

  • [myObject release]

    Hallo zusammen,

    ich hab mal ne Frage zum Thema release.
    So wie das im Hillegass beschrieben ist, versteh ich es nicht ganz.

    In Kapitel 4 heißt es unter der Überschrift "Creating Autoreleased Objects"

    Our next attempt might look something like this:

    Quellcode

    1. - (NSString *)description
    2. {
    3. NSString *result;
    4. result = [[NSString alloc] initWithFormat:@"%@ = %d and %d",
    5. [entryDate descriptionWithCalendarFormat:@"%b %d %Y"],
    6. firstNumber, secondNumber];
    7. [result release];
    8. return result;
    9. }


    [color="blue"]This code would not work at all.[/color] When sent the message release, the string's retain count would go to zero, and the string would be deallocated. The object asking for the string would get a pointer to a freed object.


    Das komische ist, dass es bei mir (unter 10.5) aber doch funktioniert. Ich habe dann über der Zeile
    [result release]
    folgendes eingefügt:

    i = [result retainCount];
    NSLog(@"retainCount of %d",i);

    Das gibt mir jeweils einen retainCount von 1 aus, nach der " [result release]" Nachricht sollte der also 0 sein und der String "deallocated" (gibt es da ein deutsches Wort dafür?) werden.

    Das Programm läuft aber dennoch ganz normal und das verstehe ich eben nicht.
    Erst wenn ich zwei release Nachrichten an result schicke, gibts einen Laufzeitfehler bei jedem Schleifendurchlauf:
    "lottery(28814) malloc: *** error for object 0x108220: double free"

    Gruß
    D.Mon
    Habe Mut, Dich Deines eigenen Verstandes zu bedienen.
    (Immanuel Kant)
  • nicht das release dealloziert den speicher sondern das passiert in der runloop IRGENDWANN. Und es wird dann auch noch an der stelle im speicher liegen - bis es von irgendwas überschrieben wird. das kann man aber weder steuern noch wissen. also kann es sein dass es 999 mal funktioneirt und dann einmal nicht.
  • RE: [myObject release]

    Löschen bedeutet nur, dass der Speicher als frei markiert wird. Es kann sein, dass du noch eine ganze Weile auf ih zugreifen kannst und die "echten Daten" erhältst. Irgendwann wird er überschrieben und dann geht's den Bach herunter. Das ist so ähnlich wie mit gelöschten Dateien auf der Festplatte. Die stehen da auch noch eine ganz Weile, aber eben nicht mehr verlässlich.

    Wen du das übrigens genauer untersuchen willst, kannst du mal nach NSZombie googlen.
    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"?
  • Original von gritsch
    nicht das release dealloziert den speicher sondern das passiert in der runloop IRGENDWANN.
    ...

    Da verstehe ich die Doku aber anders:

    release
    ...
    Discussion
    The receiver is sent a dealloc message when its reference count reaches 0.


    Ich nehm's jetzt einfach mal so zur Kenntnis, wie Ihr das hier schreibt, aber verstanden habe ich es, ehrlich gesagt, noch nicht ganz.

    Das entscheidende ist vermutlich dass die Daten noch im Speicher liegen, auf den der Pointer zeigt.
    Das Objekt an sich stirbt aber wahrscheinlich, sobald der retainCount 0 wird.
    Kann man das so sagen?

    Irritiert hat mich, dass der Hillegass ausdrücklich schreibt "This code would not work at all." Nichts von "unzuverlässig" oder so.

    Danke und Gruß
    D.Mon
    Habe Mut, Dich Deines eigenen Verstandes zu bedienen.
    (Immanuel Kant)
  • Original von D.Mon
    Irritiert hat mich, dass der Hillegass ausdrücklich schreibt "This code would not work at all." Nichts von "unzuverlässig" oder so.
    Weil er nicht sicherstellen kann dass es nur "unzuverlässig" arbeitet. Dann kommt nämlich einer und stellt fest dass es bei ihm nie geht und beschwert sich dass er nicht schreibt: "This code would not work at all.".

    Was mich eher wundert ist dass er das überhaupt das Ganze als Experiment aufbaut und versucht mit einem Negativbeispiel zu erklären. So als ob man dem Kochlehrling erst mal eine versalzene Suppe kochen lassen muss nur um dann zu zeigen wie es richtig gewesen wäre.

    Der wundert sich dann (wie Du) nur weil er von selbst nie auf die falsche Lösung gekommen wäre.

    Ich habe den Hillegass nie gelesen, aber wenn er das so als Experiment aufbaut, dann wundert mich nicht mehr so sehr warum so viele der Meinung sind dass man das mit retain/release ausprobieren muss und es keine klaren Regeln gibt.

    -- hns

    PS: die Erklärung von gritsch ist auch nicht ganz korrekt. Der dealloc findet schon beim release statt - nur irgendwann auf dem Weg in die Runloop wird der Speicher dann neu vergeben.
  • Original von D.Mon
    Original von gritsch
    nicht das release dealloziert den speicher sondern das passiert in der runloop IRGENDWANN.
    ...

    Da verstehe ich die Doku aber anders:

    release
    ...
    Discussion
    The receiver is sent a dealloc message when its reference count reaches 0.


    Ich nehm's jetzt einfach mal so zur Kenntnis, wie Ihr das hier schreibt, aber verstanden habe ich es, ehrlich gesagt, noch nicht ganz.


    Naja, da steht, dass das Objekt eine -dealloc Nachricht erhält, wenn sein RC 0 ist.
    Was passiert im -dealloc?
    Es gibt seine Daten frei und sendet super ebenfalls eine -dealloc Nachricht.
    Wann führt das Objekt seine -dealloc-Methode aus?
    Tja...
    Bei zeitkritischen Anwendungen wäre es Blödsinn, die Methode sofort auszuführen. Da sollte man lieber warten, bis die Anwendung eh grad nix zu tun hat.
    Bei gefühlten 2 Gigabyte freien Speicher ist es auch wurscht, ob diese paar Byte jetzt, in fünf Sekunden oder in 8 Minuten freigegeben werden.
    Eventuell ist das Objekt auch wirklich sofort tot, aber der Speicher wird nicht einfach mit Unsinn überschrieben sondern solange beibehalten, bis eine Änderung eintritt.

    Ich denke, das Objekt verhält sich in dem Fall wie eine Katze. Wenn man eine Katze ruft nimmt sie es zur Kenntnis und kommt gegebenenfalls darauf zurück. ;)

    Auch die Doku erzählt dir nur, dass das Objekt seine -dealloc Nachricht erhält. Du findest beim Überfliegen der Doku keinen Anhaltspunkt darüber, wann das Objekt auf diese -dealloc Nachricht hört.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Original von Lucas de Vil
    ...
    Auch die Doku erzählt dir nur, dass das Objekt seine -dealloc Nachricht erhält. Du findest beim Überfliegen der Doku keinen Anhaltspunkt darüber, wann das Objekt auf diese -dealloc Nachricht hört.

    Das vielleicht nicht, aber im neuen Negm-Awad steht in Kapitel 1, dass Methoden "klassisch" abgearbeitet werden, "Schritt für Schritt". Da steht nichts von "warten, bis die Anwendung eh grad nix zu tun hat".
    Vielleicht sitze ich einem Irrtum auf, aber ich hatte das so verstanden, dass Nachrichten an Objekte den Aufruf von Methoden auslösen, die dann sofort prozedural abgearbeitet werden.

    Gruß
    D.Mon
    Habe Mut, Dich Deines eigenen Verstandes zu bedienen.
    (Immanuel Kant)
  • Original von D.Mon
    Original von Lucas de Vil
    ...
    Auch die Doku erzählt dir nur, dass das Objekt seine -dealloc Nachricht erhält. Du findest beim Überfliegen der Doku keinen Anhaltspunkt darüber, wann das Objekt auf diese -dealloc Nachricht hört.

    Das vielleicht nicht, aber im neuen Negm-Awad steht in Kapitel 1, dass Methoden "klassisch" abgearbeitet werden, "Schritt für Schritt". Da steht nichts von "warten, bis die Anwendung eh grad nix zu tun hat".
    Vielleicht sitze ich einem Irrtum auf, aber ich hatte das so verstanden, dass Nachrichten an Objekte den Aufruf von Methoden auslösen, die dann sofort prozedural abgearbeitet werden.

    Methoden werden klassisch, Schritt für Schritt prozedural abgearbeitet, ja.
    Nachrichten an Objekte lösen den Aufruf von Methoden aus, ja.

    Aber spätestens wenn du im Kapitel 6 an der Responder Chain vorbei kommst erkennst du, dass das eben nicht soooo einfach ist.

    Sende ich die Nachricht -tuWas an die Responder Chain, dann hangelt sich diese Nachricht notfalls bis ins allerletzte Objekt durch, in der Hoffnung, dass sie erhört wird.
    Vielleicht hört ein Objekt ja auf -tuWas; führt aber seine Methode -schliessDieFensterUndLoeschDasLicht aus.

    Dein Objekt bekommt ein -dealloc, da der RC auf 0 steht.
    Gesetzt dem Fall das Objekt reagiert sofort, dann räumt es auf und sendet seiner Superklasse ebenfalls ein -dealloc. Dein Objekt ist nun quasi weg. Im Speicher kann es immer noch hängen.

    Fünfhundert deiner Objekt bekommen ein -dealloc, da ihr RC auf 0 steht. Alle nacheinander.
    So ein Prozessor ist zwar schnell, aber er kann ja nicht alles auf einmal und obendrein noch gleichzeitig machen.
    Erst einmal wird prozedural deine aktuelle Methode (500 -deallocs) abgearbeitet. Dein erstes Objekt bekommt ein -release, dein zweites auch und irgendwann dein 500es.
    Wird jetzt nach jedem -release ins -dealloc gesprungen? Oder erst, wenn deine Methode verlassen wird und zu den 500 freigegebenen Objekten keines mehr hinzu kommt?
    Ich weiß es nicht, es ist auch für mich unerheblich.

    Deine Theorie stimmt, aber du rufst -dealloc ja nicht selbst auf. Du schickst nur ein -release.

    -dealloc wird vom 'System' aufgerufen.
    Ich weiß nicht von wem genau. Du weißt nicht von wem genau. Einige wissen von wem genau.
    Ich weiß nicht wann. Du weißt nicht wann. Einige wissen wann.
    Ich weiß nicht, wann der Speicher neu verteilt wird. Du weißt nicht, wann der Speicher neu verteilt wird. Einige wissen, wann der Speicher neu verteilt wird.

    Aber im Grunde genommen ist es völlig unerheblich.

    Gib Speicher am Ende frei, wenn du die Objekte definitiv nicht mehr brauchst. Meist im -dealloc deiner eigenen Klassen.
    Nimm wo du kannst einen Autoreleasepool. Bei stark verschachtelten Schleifen mit hohem Durchlauf einen Eigenen, den du ab und an eigenhändig leerst.
    Pass auf, dass du -retain und -copy bei deinen Accessoren richtig nutzt.
    Und du wirst keinerlei Speicherprobleme bekommen.

    Selbst wenn du nicht weißt, wer wann das -dealloc sendet und wie anschließend der Speicherplatz neu verteilt wird.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Aaaaaaaaaaaaaalso, mal vom Autor:

    1. Zum eigentlichen Problem
    AFAIK ist es tatsächlich so, dass -release unmittelbar -dealloc aufruft, wenn der RC auf 0 geht und -dealloc in der Standardimplementierung den Speicher freigibt. Es funktioniert also wirklich klassisch.

    2. Zum "Sofort"
    Aber das ist auch unerheblich, weil das nur scheinbar Widerspruch ist: Jede Nachricht wird klassisch ausgeführt. Allerdings gibt es die Nachricht: Speichere in der Runloop. Die wird dann auch sofort ausgeführt. Das was aber in der Runloop gespeichert wird, ist natürlich in der Runloop. Du wirst im weiteren Verlauf des Buches auch noch Beispiele dafür sehen und damit selbst herumkaspern. Wir hatten hier erst letztens einen Thread mit -add: (NSArrayController)

    Aber jede Nachricht, die du siehst, wird unmittelbar ausgeführt. Das bedeutet nicht, dass man nicht auch Nachrichten auf Vorrat speichern kann. Da steht dann aber anstelle von

    [receiver message]; // sofort

    so etwas wie

    [receiver performSelectorOnMainThread:@selector( message ) …];

    Auch diese Nachricht wird sofort ausgeführt, nur eben nicht die gespeicherte. (Eigentlich ist das noch gar keine Nachricht, es wird noch eine.)

    Aller Klarheiten beseitigt?
    +++
    Vielleicht ein Beispiel aus der "wirklichen Welt":
    Befehl: Merke dir, dass du morgen Brötchen kaufen musst!

    Der Befehl liegt im "merke dir". Dies führst Du sofort aus. Der Befehl speichert aber (merken) einen Befehl der sich erst morgen aktualisiert. Den führst du dann morgen aus. Das ist aber auch erst morgen ein Befehl.

    Äh, irgendwie verständlich?
    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"?
  • Original von D.Mon
    Original von gritsch
    nicht das release dealloziert den speicher sondern das passiert in der runloop IRGENDWANN.
    ...

    Da verstehe ich die Doku aber anders:

    release
    ...
    Discussion
    The receiver is sent a dealloc message when its reference count reaches 0.


    Ich nehm's jetzt einfach mal so zur Kenntnis, wie Ihr das hier schreibt, aber verstanden habe ich es, ehrlich gesagt, noch nicht ganz.

    Musst du auch nicht. Ich halte die Doku für richtig: Wenn der RC auf 0 geht, wird -dealloc ausgeführt und die Basisimplementierung markiert den Speicher auch als frei. (Das ist löschen!).

    Ich habe das zwar nie nachgeprüft, aber das verschieben auf die Runloop wäre kontraproduktiv, so dass ich mir das nicht vorstellen kann.

    Original von D.Mon
    Das entscheidende ist vermutlich dass die Daten noch im Speicher liegen, auf den der Pointer zeigt.
    Das Objekt an sich stirbt aber wahrscheinlich, sobald der retainCount 0 wird.
    Kann man das so sagen?

    Irritiert hat mich, dass der Hillegass ausdrücklich schreibt "This code would not work at all." Nichts von "unzuverlässig" oder so.

    Das ist auch richtig. Wenn das Ergebnis nicht zuverlässig vorherbestimmt werden kann, ist es fehlerhaft. Fehlerfrei ist nicht dann ein Programm, wenn es mal funktioniert, mal nicht, sondern, wenn es zuverlässig funktioniert.

    Das meint Hillegass einfach damit.
    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"?
  • Vielen Dank für die ausführlichen Stellungnahmen.

    Insgesamt ist mir die Thematik des "Retain Count" noch nicht annähernd klar.
    Vor allem ist mir unklar, wann den nun der retain Count eines Objekts automatisch erhöht wird und wann ich das "von Hand" machen muss.
    Auch ist mir nicht hundertprozentig klar, ob ein Objekt immer von mir in den autorelease pool gesteckt werden muss oder ob das manche Methoden selbständig machen.

    Die Ausführungen im Hillegass versteh ich da noch nicht so ganz.
    Er schreibt:

    The alloc operation always yields an object with a retain count of 1; thus, the string being returned has a retain count of 1. Any object asking for the string would retain it. The string would then have a retain count of 2. When no longer interested in the string, the object would release it.

    Das würde doch bedeuten, dass durch den Aufruf von

    Quellcode

    1. NSLog(@"%@", entryToPrint);


    der retainCount von "result" auf 2 erhöht wird, richtig?

    Was genau bedeutet in diesem Zusammenhang:
    When no longer interested in the string, the object would release it.


    Auch die Rules Concerning Release sind mir nicht ganz klar.

    Objects created by alloc, new, copy, or mutableCopy have a retain count of 1 and are not in the autorelease pool.

    Soweit bin ich noch dabei, aber

    If you get an object by any other method, assume that it has a retain count of 1 and is in the autorelease pool. If you do not wish it to be deallocated with the current autorelease pool, you must retain it.

    Warum soll man annehmen, dass das Objekt im autorelease pool ist? Bei -initWithFormat ist das ja offensichtlich nicht der Fall, sonst müsste ich es da nicht hineinstecken.

    Im nächsten Satz heißt es dann:
    Because you will frequently need objects that you are not retaining, many classes have class methods that return autoreleased objects

    Das heißt doch im Umkehrschluss, dass viele Methoden Objekte zurück geben, die nicht "autoreleased" sind.

    Noch was (das Beispiel mit den Farben):
    Wie sieht das aus, wenn mehrere Objekte pointer auf ein anderes Objekt haben.
    Wenn das andere Objekt im autorelease pool ist, wird doch bei "pool drain" nur ein release gesendet.
    Wenn der retainCount > 1 ist, überlebt das Objekt also. Wie unterscheidet man hier, ob man ein Objekt ganz loswerden möchte oder ob nur der retainCount um eins vermindert wedren soll.

    Außerdem noch:
    Wenn mehrere Objekte ein [myObject autorelease] senden, wird dann bei [pool drain] nur ein release an das Objekt gesendet oder mehrere?


    Vielleicht klärt sich das im Verlauf des weiteren Lesens noch, im Augenblick ist da jedenfalls noch eine dicke undurchdringliche Wolke und jede Aufhellung ist mir mehr als Willkommen.

    Gruß
    D.Mon
    Habe Mut, Dich Deines eigenen Verstandes zu bedienen.
    (Immanuel Kant)
  • Das "asking" istmindestens missverständlich. Auch der Rest ist nicht falsch, aber in der Tat sehr missverständlich. Ich kann das jetzt hier alles auf dröseln, aber das habe ich ja schon gemacht. Der Hillegass ist sicher ein gutes Buch, der Abschnitt über Speicherverwaltung aber nicht.

    Du hast ja auch mein Buch. Ich mache das ausführlicher. Lies das einmal, dann noch einmal das im Hillegass, vielleicht noch einmal bei mir. Dann dürftest du es so langsam drin haben. Du kannst auch meinen Artikel auf der Wiki lesen:
    wiki.osxentwicklerforum.de/dok…wiki:speicherverwaltung&s[]=speicherverwaltung

    Du kannst auch einfach meine Handwerksregeln benutzen. Die sind eigentlich zu verstehen,weil man dazu nicht alles verstanden haben muss.
    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"?
  • Original von D.Mon
    The alloc operation always yields an object with a retain count of 1; thus, the string being returned has a retain count of 1. Any object asking for the string would retain it. The string would then have a retain count of 2. When no longer interested in the string, the object would release it.

    Das würde doch bedeuten, dass durch den Aufruf von

    Quellcode

    1. NSLog(@"%@", entryToPrint);


    der retainCount von "result" auf 2 erhöht wird, richtig?


    Falsch.
    Any object asking for the string bezieht sich auf Dinge wie [array addObject:result]; oder [object setResultString:result]; Von mir aus auch [view setDelegate:result];
    NSLog macht mit dem Objekt rein gar nix, es gibt nur den Rückgabewert aus.
    Auch

    Quellcode

    1. NSLog(@"%@", [result stringValue]);

    macht mit dem Objekt nix außer ihm eine Nachricht senden.
    (Gibst du dem Objekt im NSLog keine Nachricht mit, versendet NSLog automatisch ein -description, wenn ich mich recht entsinne)

    Jedes Objekt, dass irgendwie mit 'set' oder 'add' eine Referenz auf dein Objekt speichert erhöht den RC um 1.

    Genau deshalb soll man immer Accessoren nutzen. ;)


    Was genau bedeutet in diesem Zusammenhang:
    When no longer interested in the string, the object would release it.

    Hast du den Negm-Awad? Der erklärt das recht anschaulich.

    Quellcode

    1. NSObject* result = [[NSObject alloc] init]; //RC 1 wegens INIT
    2. [anArray addObject:result] //RC 2 wegens addObject - anArray verweist aufs result
    3. [result release] // RC 1 weil result released, hängt aber noch in anArray
    4. [aSet addObject:[anArray objectAtIndex:0]] // RC 2 weil aSet auch an dem hängt das mal result war
    5. [aSet release]; //RC 1 weil das verweisende Set verschwindet und den Verweis auf result mitreißt
    6. [[anArray objectAtIndex:0] release] // RC 0, weil auch das Array den Verweis auf ehemals result endlich los lässt
    7. /* Auch hier sollte man lieber removeObject oder Equivalentes nehmen! Habs nur zur Erläuterung falsch gemacht. Preisfrage: was ist daran falsch? ;) */



    Auch die Rules Concerning Release sind mir nicht ganz klar.

    Objects created by alloc, new, copy, or mutableCopy have a retain count of 1 and are not in the autorelease pool.

    Soweit bin ich noch dabei, aber

    If you get an object by any other method, assume that it has a retain count of 1 and is in the autorelease pool. If you do not wish it to be deallocated with the current autorelease pool, you must retain it.

    Warum soll man annehmen, dass das Objekt im autorelease pool ist? Bei -initWithFormat ist das ja offensichtlich nicht der Fall, sonst müsste ich es da nicht hineinstecken.


    Klar, bei -initWithFormat nicht. Ist ja ein -init. Heißt etwas anders, aber nur weil es ein -init mit Werten ist.
    Beim Convenience Allocator [MyResult resultWithFormat:@"%d"]; musst du aber davon ausgehen, dass es im ARP landet. Ansonsten ist dein Convenience Allocater falsch. Lies den Negm-Awad.


    Im nächsten Satz heißt es dann:
    Because you will frequently need objects that you are not retaining, many classes have class methods that return autoreleased objects

    Das heißt doch im Umkehrschluss, dass viele Methoden Objekte zurück geben, die nicht "autoreleased" sind.

    Hauptsächlich die, die du per -init, -new, -copy oder -mutableCopy erstellst.
    Und diejenigen, deren Convenience Allocator du falsch gebastelt hast. ;)


    Noch was (das Beispiel mit den Farben):
    Wie sieht das aus, wenn mehrere Objekte pointer auf ein anderes Objekt haben.
    Wenn das andere Objekt im autorelease pool ist, wird doch bei "pool drain" nur ein release gesendet.
    Wenn der retainCount > 1 ist, überlebt das Objekt also. Wie unterscheidet man hier, ob man ein Objekt ganz loswerden möchte oder ob nur der retainCount um eins vermindert wedren soll.

    Gar nicht. DU entscheidest überhaupt nicht, ob das Objekt ganz entfernt wird. DU entscheidest nur, ob DU das Objekt noch brauchst. Siehe die Spielerei oben und den Negm-Awad.

    Außerdem noch:
    Wenn mehrere Objekte ein [myObject autorelease] senden, wird dann bei [pool drain] nur ein release an das Objekt gesendet oder mehrere?


    [pool drain] sendet IIRC ein Release an alle Objekte im entsprechenden Autoreleasepool.


    Vielleicht klärt sich das im Verlauf des weiteren Lesens noch, im Augenblick ist da jedenfalls noch eine dicke undurchdringliche Wolke und jede Aufhellung ist mir mehr als Willkommen.


    Ich kann da den Negm-Awad empfehlen. ;)
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Etwas korrigieren muss ich: Es gibt Setter, die kein -retain ausführen. -setDelegate: ist nun so gerade ein Dingens. Warum man das manchmal machen muss, erläutere ich auf Seite 246 ff. (Retain-Zyklen)

    Zum -init bei Euch beiden: Eigentlich wird das Objekt ja bereits von dem +alloc erzeugt. Das -init initialisiert es nur. (Was manchmal eine Neuerzeugung ist, aber das führt wirklich zu weit.)
    +++
    Aber in der Tat nimmt man den Rückgabewert von -init, insofern ist der Satz von Hillegass nackt betrachtet so nicht richtig.
    /+++

    Was Hillegass mit "assume to be autoreleased" meint, ist nicht, dass es im ARP ist. Das sagt er ja auch nicht. Er meint nur: Du kannst dich nicht darauf verlassen, dass es bestehen bleibt, also behandele es so, als ob es demnächst vom ARP gelöscht würde.

    Oder anders gesagt: Wenn man ein Objekt behalten will, muss man ein -retain drauf machen.
    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"?
  • Ja, ich hab beide Bücher und arbeite abwechselnd und parallel damit.

    Mir ist klar, dass man das nicht alles an einem kalten Nachmittag verstehen kann.
    Aber ich bin halt manchmal etwas ungeduldig ;).
    Ich denke, die grundsätzliche Problematik habe ich begriffen und mit dem Handwerkszeug werde ich einfach üben und viel lesen müssen.

    Jedenfalls Danke an Euch für die vielen Erklärungen.

    Gruß
    D.Mon
    Habe Mut, Dich Deines eigenen Verstandes zu bedienen.
    (Immanuel Kant)
  • Original von D.Mon
    Ja, ich hab beide Bücher und arbeite abwechselnd und parallel damit.

    Mir ist klar, dass man das nicht alles an einem kalten Nachmittag verstehen kann.
    Aber ich bin halt manchmal etwas ungeduldig ;).
    Ich denke, die grundsätzliche Problematik habe ich begriffen und mit dem Handwerkszeug werde ich einfach üben und viel lesen müssen.

    Jedenfalls Danke an Euch für die vielen Erklärungen.

    Gruß
    D.Mon

    Ich will es mal so sagen: Deine Fragen zeigen, dass du es grundsätzlich begriffen hast. :)
    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"?
  • Der Abschnitt über Speicherverwaltung in Kapitel 3 im Buch sind wirklich gut.
    Die Erklärungen im Buch sind sehr ausführlich und hilfreich.
    Bin zurzeit auf Seite 240 Mitte.

    Jetzt habe ich folgende Frage zur Thematik.

    Es könnte ja sein, dass unsere Person, die Gruppenleiter ist, irgendwo im Programm unter bestimmten Bedingungen verstirbt.
    Ich hab mir überlegt, was da wohl passieren müsste, damitt alles ordentlich aufgeräumt wird.

    Ein -retain würde nicht genügen, da der RC ja auf 2 steht (und grundsätzlich noch höher stehen könnte). Zuerst dachte ich klar, kein Problem, [aPerson dealloc] macht die Person ja weg — macht sie auch, aaaber: ganz hinten kommt ja noch unser [aPerson release] und das führt dann zwnagsläufig zu einem Laufzeitfehler "message release sent to freed object"

    Wie wird so etwas gehandhabt?
    Kann man mit einer Bedingung feststellen, ob es das Objekt, auf das aPerson zeigt, überhaupt noch gibt und -releas dann in eine entsprechende if-Abfrage packen. Oder gibt es dafür einen ganz anderen Lösungsansatz?

    Ein weiteres Problem ist, dass die Gruppe nun einen leader eingetragen hat, den es gar nicht mehr gibt. Auch das führt beim Ableben der Person u.U. zu Laufzeitfehlern. In dem Zusammenhang ist mir außerdem aufgefallen, dass eine Gruppe zwar "weiß", wer ihr Leiter ist, diese Person, weiß aber nichts von dieser Eigenschaft (bzw. Beziehung). Das bedeutet aber im Umkehrschluss, dass ich, wenn ich die Gruppenmitgliedschaft nicht über [aPerson dealloc] beenden kann.
    Habe Mut, Dich Deines eigenen Verstandes zu bedienen.
    (Immanuel Kant)
  • Original von D.Mon
    Es könnte ja sein, dass unsere Person, die Gruppenleiter ist, irgendwo im Programm unter bestimmten Bedingungen verstirbt.


    Soweit ich mich erinnere gibt das aktuelle Modell das gar nicht her.

    -setLeader erhöht den RC der Person um eins.
    'Stirbt' die Person, muss der Leader auch entfernt werden.

    Du machst einfach kein Retain sondern ein Assign (leader = aPerson) in deiner Gruppe.
    Das sorgt dafür, dass du nur einen Verweis hast. Ist die Person weg ist auch der Posten weg. Zugriff auf fehlende Personen ist natürlich nicht möglich.

    Du brauchst also im Idealfall einen Controller, der irgendwie -personIsDead:(Person*)aPerson implementiert.
    Dann schaust du, ob [gruppe leader] identisch zu aPerson ist und wirfst ihn raus. Anschließend ernennst du schnell einen Nachfolger oder lässt die Position unbesetzt.


    Original von D.Mon
    Kann man mit einer Bedingung feststellen, ob es das Objekt, auf das aPerson zeigt, überhaupt noch gibt und -releas dann in eine entsprechende if-Abfrage packen. Oder gibt es dafür einen ganz anderen Lösungsansatz?


    Dafür gibt es Controller. Deinem Modell ist es wurscht, wer es wie wann wieso warum weshalb nutzt.

    Original von D.Mon
    In dem Zusammenhang ist mir außerdem aufgefallen, dass eine Gruppe zwar "weiß", wer ihr Leiter ist, diese Person, weiß aber nichts von dieser Eigenschaft (bzw. Beziehung). Das bedeutet aber im Umkehrschluss, dass ich, wenn ich die Gruppenmitgliedschaft nicht über [aPerson dealloc] beenden kann.


    Du kannst natürlich eine Beziehung leaderOfGroup in deine Person einbauen. So wie es auch in CoreData gemacht werden sollte.
    Ach, und DU sollst gar nix über -dealloc beenden. ;)
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P