Speicherverwaltung Begriffsdefinition

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Ich weiß jetzt nicht genau, von welchem Code du sprichst, da hier ja schon einiger herumfliegt.
    Dieser Code ist gemeint. Nach Lukas Aussage wird y und z nicht freigegeben, da nichts mehr darauf zeigt (ich hoffe, ich gebe das richtig wider).

    Quellcode

    1. MyObject* object = [[MyObject alloc] init] //x hat nen RC1 durchs alloc
    2. [object setField1:[[MyObject alloc] init]] //y hat nen RC1 durchs alloc, RC2 durch den Retain-Setter
    3. [object setField2:[[MyObject alloc] init]] //z hat nen RC1 durchs alloc, RC2 durch den Retain-Setter
    4. [object setField1:[object field2]] //x RC1, y RC1 durchs Release im Setter, z RC3 durch den zweiten Setter
    5. [object release]; // x RC0 durchs Release, y bleibt bei RC1, z RC1 durchs Release von field1 und field2


    Nachdem desöfteren der Tipp mit dem ARP kam, war die Frage, ob ich dieses Leck umgehen kann, wenn ich alle Objekte in diesem Schnippsel gleiche autorelease um so zu verhindern, dass mir die ursprüngliche Referenz verschüttgeht und ich nicht mehr freigeben kann.

    Hans
  • Nee, es ging ja jetzt um seine Aussage, dass der ARP etwas freigeben kann. Wenn du hier den ARP einsetzt, passiert gar nichts, weil der ARP selbst erst am Ende freigegeben wird.

    Generell ist es richtig, dass du mit dem ARP es nicht vergisst, die ursprüngliche Referenz aufzugeben. Außerdem, wenn das wie hier ein anonymes Objekt ist, geht es auch nur so. Aber das sind ja alles nur Bequemlichkeitsfragen. Du kannst ja ohne Not schreiben:

    Quellcode

    1. MyObject* object = [[MyObject alloc] init];
    2. y = [[MyObject alloc] init];
    3. [object setField1:y];

    Und dann könntest du explizit aufgeben.

    Quellcode

    1. [y release];

    Der Unterschied liegt ja nur in der Bequemlichkeit, Schreibarbeit nicht aber in der Funktion.

    Der wirkliche Vorteil kommt zum tragen, wenn du Instanzen zurückgibst. Aber darum geht es hier nicht.
    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"?
  • Vielleicht hat es jetzt "klick" gemacht ??
    Ich habs mir jetzt sicher noch 5x angeschaut und wenn ich richtig liege, muss ich zugeben, dass alles eigentlich schon da stand, nur hab ichs nicht kapiert.

    Also, nochmals der Code-Fetzen mit den Anmerkungen von Lukas de Vil

    Quellcode

    1. 1 MyObject* object = [[MyObject alloc] init] //x hat nen RC1 durchs alloc
    2. 2 [object setField1:[[MyObject alloc] init]] //y hat nen RC1 durchs alloc, RC2 durch den Retain-Setter
    3. 3 [object setField2:[[MyObject alloc] init]] //z hat nen RC1 durchs alloc, RC2 durch den Retain-Setter
    4. 4 [object setField1:[object field2]] //x RC1, y RC1 durchs Release im Setter, z RC3 durch den zweiten Setter
    5. 5 [object release]; // x RC0 durchs Release, y bleibt bei RC1, z RC1 durchs Release von field1 und field2


    Zeile 2 : Wie Lukas schreibt : Mit [[MyObject alloc] init] wird ein Objekt erzeugt (wg. alloc -> RC=1).
    obj.field1 meldet Besitz an (sagt man das so?) bzw. kriegt dieses Objekt über den Setter zugewiesen, weswegen der RC sich nochmals um eins erhöht.

    Zeile 3 lass ich mal ausser Acht, hier gilt ja das Analoge wie für field1

    Zeile 4 : obj.field1 kriegt einen neuen Wert (objekt) zugewiesen. Das alte erhält im Setter ein Retain und geht auf 1 zurück.
    Dieses übriggebliebene RC kann ich aber nicht freigeben und habe ein Seicherleck

    Wenn ich stattdessen schreibe :

    Quellcode

    1. MyObject* object = [[MyObject alloc] init];
    2. MyObject* feld1 = [[MyObject alloc] init];
    3. MyObject* feld2 = [[MyObject alloc] init];
    4. [object setField1:feld1];
    5. [object setField2:feld2];
    6. [object setField1:[object field2]];
    7. [feld1 release];
    8. [feld2 release];
    9. [object release];
    Alles anzeigen


    hätte ich jetzt über feld1 und feld2 noch die Möglichkeit den vorher nicht freizugebenden RC zu verringern und das Speicherleck wäre weg ??

    Hab ich was übersehen ?

    Hans
  • Amin Negm-Awad schrieb:

    Lucas: "Wenn Sie Ihren Laptop in die gefüllte Badewanne werfen, dann muss ich ihn abtrocknen."
    Amin: "Nein du sollst ihn gar nicht in die gefüllte Badewanne werfen."
    Lucas wirft den Laptop in die gefüllte Badewanne. "Ja was denn nun? Jetzt muss ich ihn doch abtrocknen, oder nicht?"

    Genau das meine ich mit 'unterschiedliche Interpretation von richtig'.
    Amins Antwort ist in dem Beispiel aus meiner Sicht schlicht falsch.

    Korrekt wäre:
    Lucas: "Wenn Sie Ihren Laptop in die gefüllte Badewanne werfen, dann muss ich ihn abtrocknen."
    Amin: "Stimmt. Du bist aber hoffentlich nicht so bedeppert, das Ding in die gefüllte Badewanne zu werfen."

    Ich sage, ich kann mehrfach Besitz anmelden und muss ihn entsprechend wieder weggeben.
    Du sagst, ich kann nur einmal Besitz anmelden, dann gehört die Instanz mir und mir kann sie keiner nehmen.
    Ich sage, ich kann sehr wohl mehrfach Besitz anmelden, obwohl ich das nicht tun sollte.
    Du sagst, ich kann es nicht, sondern nur den RetainCount erhöhen.

    Da frage ich mich: wo genau liegt der Unterschied? Egal wie viele Besitzer die Instanz hat, wenn ich den Fehler mache zweimal Besitz anzumelden (oder den RetainCount um eins zu erhöhen), dann muss ich die Instanz auch zwei mal abmelden (oder den RetainCount um eins reduzieren). Punkt Aus Ende Feierabend.
    Es ist Fakt, dass eine derartige Aktion Schwachsinn und schlechter Stil ist.
    Wenn das Kind in den Brunnen gefallen und am ertrinken ist, meckert man auch nicht zwei Stunden vom Rand auf das Kind ein.
    Man holt es raus und sagt ihm, dass es das nie nie wieder machen soll.

    Zum ARP:
    Bei den hier geschriebenen Posts kann es nicht passieren, richtig.
    Mit 'Implementierung ist egal' meinte ich schlicht, ob der ARP sein Release jetzt vor dem Wiedereintritt in die Runloop oder erst beim erneuten Verlassen dieser bekommt.
    Mehr nicht.
    Weiterhin stimme ich dir zu, dass die Nutzung des ARP nicht das Verständnis aushebelt.
    «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
  • HansGerber schrieb:

    >>>Zeile 4 : obj.field1 kriegt einen neuen Wert (objekt) zugewiesen. Das alte erhält im Setter ein RELEASE und geht auf 1 zurück.

    Wahrscheinlich die Aufregung...

    Wenn das jetzt stimmt, dann ist mir auch klar, warum man

    Quellcode

    1. [object setField2:[[MyObject alloc] init]]


    eigentlich nicht machen sollte.

    Hans


    Hervorragend. :)
    «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
  • Lucas de Vil schrieb:

    Amin Negm-Awad schrieb:

    Lucas: "Wenn Sie Ihren Laptop in die gefüllte Badewanne werfen, dann muss ich ihn abtrocknen."
    Amin: "Nein du sollst ihn gar nicht in die gefüllte Badewanne werfen."
    Lucas wirft den Laptop in die gefüllte Badewanne. "Ja was denn nun? Jetzt muss ich ihn doch abtrocknen, oder nicht?"

    Genau das meine ich mit 'unterschiedliche Interpretation von richtig'.
    Amins Antwort ist in dem Beispiel aus meiner Sicht schlicht falsch.

    Korrekt wäre:
    Lucas: "Wenn Sie Ihren Laptop in die gefüllte Badewanne werfen, dann muss ich ihn abtrocknen."
    Amin: "Stimmt. Du bist aber hoffentlich nicht so bedeppert, das Ding in die gefüllte Badewanne zu werfen."

    Ääääääääähhhhhh, Lucas, genau das schreibe ich.
    Amin: "Nein du sollst ihn gar nicht in die gefüllte Badewanne werfen."

    Aber in einem Handbuch zur Pflege eines MacBooks finde ich es immer noch total falsch zu schreiben, dass man wenn man ihn in die Badewanne wirft, ihn abtrocknen muss. Da hat einzig und alleine zu stehen, dass man ihn nicht in die Badewanne wirft.

    Es geht hier nicht um ein Versehen. Oder sind bei dir die Anzahl de Retains eine Frage des Versehens? Und so erklärst du das? "Wenn du versehentlich ein Retain zu viel hast, musst du das ausgleichen" Tatsächich? Bitte nicht! Und um dieses Versehen auszugleichen machst du mal irgendwo ein Release hin? "Wenn ihr versehentlich ein Retain zu viel habt, dann müsst ihr (absichtlich oder versehentlich?) ein Release irgendwo hinpampen. Irgendwie ahnte ich das … Du solltest dich da vielleicht auch noch einmal einlesen. Speicherverwaltung ist nicht würfeln und raten.
    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"?
  • Quellcode

    1. MyObject* object = [[MyObject alloc] init];
    2. [object setField1:[[MyObject alloc] init]];
    3. [object setField2:[[MyObject alloc] init]];
    4. [object setField1:[object field2]];


    Kleine Frage am Rande: wie würde denn GC mit diesem Fehlkonstrukt in Zeile 2 und 3 umgehen ?
    Da auf das, was field1 bzw. field2 zugewiesen wird nichts zeigt, würde der GC dies dann beim nächsten Durchlauf entfernen ?

    Hans
  • Amin Negm-Awad schrieb:

    Lucas de Vil schrieb:

    Amin Negm-Awad schrieb:

    Lucas: "Wenn Sie Ihren Laptop in die gefüllte Badewanne werfen, dann muss ich ihn abtrocknen."
    Amin: "Nein du sollst ihn gar nicht in die gefüllte Badewanne werfen."
    Lucas wirft den Laptop in die gefüllte Badewanne. "Ja was denn nun? Jetzt muss ich ihn doch abtrocknen, oder nicht?"

    Genau das meine ich mit 'unterschiedliche Interpretation von richtig'.
    Amins Antwort ist in dem Beispiel aus meiner Sicht schlicht falsch.

    Korrekt wäre:
    Lucas: "Wenn Sie Ihren Laptop in die gefüllte Badewanne werfen, dann muss ich ihn abtrocknen."
    Amin: "Stimmt. Du bist aber hoffentlich nicht so bedeppert, das Ding in die gefüllte Badewanne zu werfen."

    Ääääääääähhhhhh, Lucas, genau das schreibe ich.
    Amin: "Nein du sollst ihn gar nicht in die gefüllte Badewanne werfen."

    'Nein, du sollst ihn gar nicht in die gefüllte Badewanne werfen.' ist ungleich 'Stimmt. Du bist aber hoffentlich nicht so bedeppert, das Ding in die gefüllte Badewanne zu werfen.'

    In deinem Satz widersprichst du mir vehement und begründest diesen Widerspruch mit etwas, dass damit nichts zu tun hat.
    "Nein, wenn das Ding in die Badewanne geworfen hast, musst du es nicht abtrocknen. Du sollst es gar nicht reinwerfen!"
    In meinem Satz stimmst du mir zu, erklärst zusätzlich aber, dass es ne ziemlich blöde Idee ist, es zu tun.

    Wir beide interpretieren 'Wenn Sie Ihren Laptop in die gefüllte Badewanne werfen' völlig unterschiedlich.
    Bei dir gehen die Alarmglocken an und du willst die Person davor bewahren, etwas unglaublich Dummes zu tun.
    Bei mir ist es schon zu spät, die Person hat etwas unglaublich Dummes getan. Deshalb helfe ich in diesem Fall mit Schadensbegrenzung und erkläre der Person, dass sie so einen Scheiß in Zukunft bitte lassen möge.

    In ein Handbuch des MacBooks gehört, dass man das Ding niemals ins Wasser werfen soll. In ein Handbuch des MacBooks gehört aber auch, was man zu tun hat wenn das Ding aus versehen ins Wasser gefallen ist.

    Ich zitiere mich selbst und hebe hervor:

    "Mich selbst" schrieb:

    Da frage ich mich: wo genau liegt der Unterschied? Egal wie viele Besitzer die Instanz hat, wenn ich den Fehler mache zweimal Besitz anzumelden (oder den RetainCount um eins zu erhöhen), dann muss ich die Instanz auch zwei mal abmelden (oder den RetainCount um eins reduzieren). Punkt Aus Ende Feierabend.
    Es ist Fakt, dass eine derartige Aktion Schwachsinn und schlechter Stil ist.


    Man meldet immer nur einmal Besitz an. Ansonsten macht man etwas grundlegend falsch.
    Ich sende ein +alloc*, das Ding gehört mir. Punkt. Das Einzige, was ich da jetzt noch machen muss, ist am Ende ein -release oder gleich am Anfang ein -autorelease senden.
    Ich sende ein -*copy*, das Ding gehört mir. Punkt. Das Einzige, was ich da jetzt noch machen muss, ist am Ende ein -release oder gleich am Anfang ein -autorelease senden.
    Ich sende ein -retain, das Ding gehört mir. Punkt. Das Einzige, was ich da jetzt noch machen muss, ist am Ende ein -release senden.
    Kein Autorelease? Kein Autorelease. Das -retain sende ich im Allgemeinen an Objekte, die ich autoreleased zurückbekomme.

    Ich kann [[[NSArray array] retain] autorelease]; machen. Ich kann mir auch nen Knopf an die Wange nähen und n Klavier dranhängen oder mir ein 5kg Gewicht an die zur Fortpflanzung wichtigen äußeren Organe klemmen. Ich tue allerdings nicht alles, was ich kann, wenn es totaler Schwachsinn oder schlechter Stil ist.

    Zu meiner Verteidigung muss ich sagen: ich bin aktiver Rollenspieler.
    Ich bin es gewohnt, irgendwelche absurden Eventualitäten vorgesetzt zu bekommen und bin dann versucht sie geradezubiegen und im Anschluss dafür zu sorgen, dass so ein Blödsinn nicht noch einmal passiert. Ist im Rollenspiel irgendwie produktiver als die ganze Zeit zu philosophieren, wie es dazu kommen kann.
    Insofern kann ich mein 'Sie haben Recht, das ist so. Wenngleich das völlig an den Haaren herbeigezogen ist' leider nicht einfach abschalten.
    «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
  • Diese Diskussion nimmt ja schon Loriot'sche Züge an :

    - Sie werfen sofort den Laptop ins Wasser!
    - Nein, mit Ihnen teilt mein Laptop das Wasser nicht.

    Sollte ich heute Abend meinen Laptop aus Versehen in die gefüllte Badewanne werfen , dann seid Ihr Schuld, das sag ich Euch !!
    Dann kommt Lukas zum Abtrocknen und Amin sagt : "Siehste, hättste mal nicht."

    Hans ;)
  • Richtig: Ich gebe nicht den Rat, etwas Falsches zu tun, um dann zu sagen wie man das zu korrigieren hat, sondern sage, man soll nichts Falsches tun. Sehr schön herausgearbeitet.

    Und irgendwie finde ich das total sinnvoll.

    Aber gut, Lucas, wenn du der Meinung bist, man solle Ratschläge geben, wie man den abgedruckten fehlerhaften Code wieder reparieren kann ist das deine Sache. Ich würde halt gar nicht fehlerhaften Code anraten.

    *schulterzuck*
    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"?
  • HansGerber schrieb:

    Diese Diskussion nimmt ja schon Loriot'sche Züge an :

    - Sie werfen sofort den Laptop ins Wasser!
    - Nein, mit Ihnen teilt mein Laptop das Wasser nicht.

    Sollte ich heute Abend meinen Laptop aus Versehen in die gefüllte Badewanne werfen , dann seid Ihr Schuld, das sag ich Euch !!
    Dann kommt Lukas zum Abtrocknen und Amin sagt : "Siehste, hättste mal nicht."

    Hans ;)


    Iwo, wenn ich Lucas das nächste Mal sehe, drücke ich ihm ein Handtuch in die Hand und werfe seinen Lappie in die nächste Badewanne. Ich bin mir allerdings nicht so ganz sicher, ob er wenigstens dann erkennt, dass das Blödsinn ist.
    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:

    Richtig: Ich gebe nicht den Rat, etwas Falsches zu tun, um dann zu sagen wie man das zu korrigieren hat, sondern sage, man soll nichts Falsches tun. Sehr schön herausgearbeitet.

    Wat? Nöö. Tust du nicht. Du widersprichst und begründest es mit etwas, dass nichts damit zu tun hat.
    Ja, ich ziehe mich an dem 'Nein' hoch. Dieses besagt in dem Kontext der Aussage nämlich, dass ich ein nasses MacBook nicht abtrocknen brauche.
    Du begründest 'Du brauchst ein nasses MacBook nicht abtrocknen.' mit 'Ein MacBook sollte niemals nass werden.' Diese Begründung hat nichts mit dem Thema zu tun.
    'Du brauchst ein nasses MacBook nicht abtrocknen' kann man natürlich mit ', dafür gibt es Fön/Heizkörper/Abtropfsieb.' begründen.
    Nicht aber mit 'Es sollte niemals nass werden.'

    Amin Negm-Awad schrieb:

    Aber gut, Lucas, wenn du der Meinung bist, man solle Ratschläge geben, wie man den abgedruckten fehlerhaften Code wieder reparieren kann ist das deine Sache. Ich würde halt gar nicht fehlerhaften Code anraten.


    Langsam nähern wir uns dem an, was wir beide meinen.
    Erst wird das 'was' erklärt, dann das 'wie'. Das 'wie' wird ausführlichst mit sämtlichen Interna erklärt, die so niemals nicht in einem Code zu finden sein dürfen!
    Dadurch wird es inhaltlich nicht automatisch falsch, lediglich ist es schlechter Stil. Man kann sich darüber streiten, ob jetzt 'der Besitz erneut angemeldet' oder 'der RetainCount erhöht wird'. Rein logisch passiert Letzteres, Mensch kann ja auch sein MacBook und die Badewanne nicht mehrmals besitzen. Außer, er hat einen Replikator. Selbst dann ist es aber nur das gleiche und nicht dasselbe, also -copy statt -retain.

    Wir sind uns einig: hätten sich die Autoren diese ganzen Erläuterungen an Hand von funktionalem und übersichtlichem, aber stilistisch und logisch vollkommen falschem Code erspart und einfach nur gezeigt, wie man es richtig macht, wären die Leser nicht so verwirrt.
    Dann hättest du aber keine Gelegenheit mehr darauf zu hoffen, dass sich HansGerber eventuell noch zusätzlich für dein Buch entscheidet.
    «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
  • Amin Negm-Awad schrieb:

    HansGerber schrieb:

    - Sie werfen sofort den Laptop ins Wasser!
    - Nein, mit Ihnen teilt mein Laptop das Wasser nicht.
    Sollte ich heute Abend meinen Laptop aus Versehen in die gefüllte Badewanne werfen , dann seid Ihr Schuld, das sag ich Euch !!
    Dann kommt Lukas zum Abtrocknen und Amin sagt : "Siehste, hättste mal nicht."

    Iwo, wenn ich Lucas das nächste Mal sehe, drücke ich ihm ein Handtuch in die Hand und werfe seinen Lappie in die nächste Badewanne. Ich bin mir allerdings nicht so ganz sicher, ob er wenigstens dann erkennt, dass das Blödsinn ist.

    Notiz an mich: nur noch mit dem ollen Acer in Amins Nähe kommen

    Wenn du das tust, werde ich den Lappie über der Heizung trocknen. Weil ich danach das Handtuch nämlich auch in die Badewanne getaucht und dir das klatschnasse Ding mehrmals um die Ohren gehauen habe.
    «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
  • Ich weiß nicht, ob das ein Automatismus ist. Aber [[[Class alloc] init] retain] ist inhaltlich falsch. Es erhöht einen RC doppelt, obwohl nur eine Inhaberschaft vorliegt. Das wird auch nicht durch ein späteres release richtig. Weil dann immer noch ein RC doppelt erhöht wurde, obwohl nur eine Inhaberschaft vorliegt. Du bist offensichtlich nicht bereit einzusehen, dass RC und Inhaberschaft zwei verschiedene Paar Schuhe sind, die sich Konzept und Implementierung nennen. Es haben ja jetzt schon einige versucht.

    Ansonsten ist ein oller Acer kein Laptop, sondern Schrott. Das gilt also nicht.
    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"?
  • Ganz im Ernst, vlt wäre es ja wirklich sinnvoll, ein Thread anzupinnen, in dem wir unsere Erfahrungen zu diversen Cocoa-Büchern posten können. Mittlerweile gibt es ja doch eine Menge und es ist nicht mehr so übersichtlich wie noch vor ein paar Jahren. Ich würde bei der Gelegenheit dann gleich ein kurzes Review zu ein paar Büchern schreiben, die ich in den letzten Monaten gekauft habe.