Speicherproblem "Message sent to deallocated instance"

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

  • Speicherproblem "Message sent to deallocated instance"

    Hallo Forum,

    ich verstehe gerade nur noch Bahnhof und suche Erleuchtung ;(

    Ich habe eine App für das iPad (iOS 6 und XCode 4.5.2), in der mehrere Instanzen einer kleinen Klasse (UIViewController) erzeugt und dargestellt werden. Diese Instanzen werden mit einem retain versehen (in der Deklaration der property) und in einem NSMutableArray gespeichert.
    Da ich beim Löschen einen Speicherfehler bekomme, habe ich einmal in der Methode dealloc vom Objekt DroppedItem und in der Löschmethode Haltepunkte gesetzt. Gelöscht wird hier:

    Quellcode

    1. -(void)deleteDroppedItemAtIndex:(int)index {
    2. if (index >= 0 && index < [droppedItems count]) {
    3. DroppedItem *item = [droppedItems objectAtIndex:index];
    4. [item deleteItemInDatabase];
    5. [droppedItems removeObjectAtIndex:index];
    6. [item.view removeFromSuperview];
    7. }
    8. }

    Laut Doku erwarte ich beim letzten Befehl (removeFromSuperview), das dort auch das Objekt released wird.
    If the receiver’s superview is not nil, the superview releases the receiver.
    Erstaunlicherweise aber wird das dealloc des Objektes schon beim Löschen aus dem Array (Zeile 5) aufgerufen!

    Wie geht das denn??

    Wenn das Objekt gar nicht entfernt würde, könnte ich das ja noch verstehen. Aber wie kann das Array das dealloc aufrufen...?
  • Beim Hinzufügen von einem View eines ViewControllers zu einem anderen View erhält natürlich nur der View und nicht der ViewController ein retain!

    Den passenden ViewController muss man auf andere Weise retainen, wie in Deiner App z.B. in einem MutableArray. Wenn Du den ViewController jetzt aus dem MutableArray entfernst, dann wird dieser natürlich nicht mehr von anderer Stelle retained und kann freigegeben werden.

    Wenn Du die Zeilen 5 und 6 tauschst, dann wird es problemlos funktionieren. ;)

    Alternativ kannst Du auch mit einem retain/release arbeiten, also z.B. so:

    Quellcode

    1. -(void)deleteDroppedItemAtIndex:(int)index {
    2. if (index >= 0 && index < [droppedItems count]) {
    3. // Wir benötigen Zugriff auf item bis zum Ende dieser Methode, also retain!
    4. DroppedItem *item = [[droppedItems objectAtIndex:index] retain];
    5. [item deleteItemInDatabase];
    6. [droppedItems removeObjectAtIndex:index];
    7. [item.view removeFromSuperview];
    8. // Hier wird item nicht mehr benötigt, also release!
    9. [item release];
    10. }
    11. }
    Alles anzeigen
  • MCDan schrieb:

    Beim Hinzufügen von einem View eines ViewControllers zu einem anderen View erhält natürlich nur der View und nicht der ViewController ein retain!
    Uups - wie dumm von mir, das zu übersehen ;(

    Wenn Du den ViewController jetzt aus dem MutableArray entfernst, dann
    wird dieser natürlich nicht mehr von anderer Stelle retained und kann
    freigegeben werden.
    Ich denke, die automatische Freigabe greift nur nach einem autorelease ...?
    Ich habe den ViewController doch selbst retained. Müsste er dann nicht bis zum expliziten release oder auf ewig bestehen?

    Wenn Du die Zeilen 5 und 6 tauschst, dann wird es problemlos funktionieren. ;)
    Passt!
    Allerdings gefällt mir die deine Variante noch besser, weil ich das release schon selber machen möchte.

    Danke für deine Hilfe! :thumbsup:
  • Gibbsnich schrieb:

    Ich denke, die automatische Freigabe greift nur nach einem autorelease ...?

    Ein Objekt wird freigegeben, erhält also ein dealloc, sobald durch ein release der letzte noch offene retain aufgehoben wird. Ein autorelease setzt ein Objekt nur in den Autorelease Pool, welcher beim leeren des Pool ein release bei allen im Autorelease Pool enthaltenen Objekten aufruft. Ein Objekt wird nicht zwangsläufig freigeben, nur weil es sich im Autorelease Pool befindet. Dies geschieht nur, wenn damit der letzte noch offene retain aufgehoben wird.

    Gibbsnich schrieb:

    Ich habe den ViewController doch selbst retained. Müsste er dann nicht bis zum expliziten release oder auf ewig bestehen?

    Gut, die Code Stelle mit dem retain war im o.a. Code Schnipsel zu sehen. Wenn Du tatsächlich ein zusätzliches retain auf den ViewController im Code hast, dann liegt der Fehler an einer anderen Stelle, da das DroppedItem Objekt beim Entfernen aus dem MutableArray nicht freigegeben werden dürfte, wenn es noch ein zusätzliches retain irgendwo im Code gibt.
  • Ich verstehe nicht, warum das dealloc erstaunlich ist, wenn es Atem betrifft!? Du holst dir einen Zeiger auf das Item und entfernst es aus dem Array. Wer sollte es noch halten?

    DroppedItem *item = [[droppedItems objectAtIndex:index] retain] autorelease];
    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"?
  • Lucas de Vil schrieb:

    Markus Müller schrieb:

    Hast Du schon überlegt, das Projekt nach ARC zu migrieren?

    Das löst leider auch nicht alle Probleme. ^^

    Wäre auch zu schön, wenn wir dann endlich Wohlstand für alle und den Weltfrieden hätten!
    Es löst aber genau solche Probleme wie im OP und außerdem spart man sich das Gefrickel mit retain/release/autorelease. Wie schreibt Apple selber dazu: Memory Management erfordert Perfektion im Befolgen der Regeln, etwas worin Menschen schlecht (manuelles Mry-Management) und Compiler gut sind (ARC).
  • Markus Müller schrieb:

    Lucas de Vil schrieb:

    Markus Müller schrieb:

    Hast Du schon überlegt, das Projekt nach ARC zu migrieren?

    Das löst leider auch nicht alle Probleme. ^^

    Es löst aber genau solche Probleme wie im OP und außerdem spart man sich das Gefrickel mit retain/release/autorelease.

    Ich hatte bei einem Projekt das Problem, dass iOS mir zu undefinierten Zeiten an undefinierten Stellen ein View unter dem Hintern weg gerissen hat.
    Ist lustig, wenn man dieses dann an einer anderen Stelle mit einem nil-Layer als Subview hinzufügen will.

    Es war sicherlich ein spezialgelagerter Sonderfall und nach ungefähr zwei Stunde Verzweiflung bin ich das Problem dann auch los geworden: ein 'removeFromSuperview:' zur falschen Zeit hat da wohl zwischengehauen.
    Doch hat mich ARC nicht davor bewahrt, dämliche Speicherverwaltungsfehler einzubauen.
    «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:

    Setzt du eine Technologie erst dann ein, wenn sie jeden Fehler vermeidet?

    Ich schrieb 'ARC vermeidet auch nicht jeden Speicherfehler.'
    Ich schrieb nicht 'ARC ist scheiße, benutz das bloß nicht.'

    Ich meinte 'Auch mit ARC sollte das Hirn noch wissen, was es den Programmierer tun lässt.'
    Ich meinte 'ARC nimmt einem nicht das Denken ab.'

    Ich hielt es wichtig mitzuteilen.
    «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
  • Na, ja, irgendeinen Sinn muss es ja haben, dass du auf "Es löst aber genau solche Probleme wie im OP und außerdem spart man sich das Gefrickel mit retain/release/autorelease." schreibst, dass nicht jeder Fehler vermieden wird. Und vor allem, wenn dies im Kontext von Markus' Rat geschieht, doch auf ARC umzustellen.

    Übrigens muss man mit ARC, solange man die Cocoa-Welt nicht verlässt (und selbst keine Methoden mit out-Parameter erstellt, selten), eben nicht mehr mitdenken, was retain/release/autorelease (und Ownershiptransfer) ist. Man kann komplett in Referenzen denken. Dass du (und mutmaßlich viele andere Leute hier) das so siehst, liegt schlicht daran, dass du ARC in deine gelernte MRC-Denke einsortierst. Jemand, der neu anfängt, hat damit überhaupt nichts am Hut. Für den ist es tatsächlich as easy as it should be.
    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:

    Übrigens muss man mit ARC, solange man die Cocoa-Welt nicht verlässt (und selbst keine Methoden mit out-Parameter erstellt, selten), eben nicht mehr mitdenken, was retain/release/autorelease (und Ownershiptransfer) ist. Man kann komplett in Referenzen denken.

    Mein Referenzdenken sagt mir, dass die Abstürze nicht hätten passieren dürfen. Die Abstürze hielten sich nicht dran.
    Ich habe nun eine gemäß meines Referenzdenkens unnötige Anpassung gemacht. Die Abstürze bleiben aus.
    Gemäß meines Referenzdenkens verstehe ich einfach nicht, wie ein View bestehen und dabei seinen Frame und seinen Layer verlieren kann. Das wüsste ich auch mit Ownership nicht.
    «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
  • Nein, du hast den Fehler bereits im Referenzdenken gemacht. -removeFromSuperview nahm eine Referenz weg. Hättest du /nur/ daran gedacht, wärst du mutmaßlich schneller drauf gekommen. Jedenfalls musst du nichts zu retain, release, autorelease wissen.

    War es nicht so, dass du anfangs von ARC als GC sprachst …
    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:

    -removeFromSuperview nahm eine Referenz weg.

    Ja. Nachdem ich andernorts mir das View als Referenz habe ausgeben lassen.
    Jemand anders referenzierte also weiterhin auf das View.

    Amin Negm-Awad schrieb:

    War es nicht so, dass du anfangs von ARC als GC sprachst …

    Stimmt. So war es nicht.
    «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
  • Oben:
    Du hast zur Erläuterung nicht einmal eines der Wörter retain, release, autorelease verwenden müssen …

    Unten:
    Na, ja
    "Ach, ARC ist der aktuelle GC-Abklatsch, der sich die nächsten drei Jahre nicht durchsetzen wird?"
    iOS und Garbage Collection - warum?
    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"?
  • Unten:
    Naja.

    Lucas de Vil schrieb:

    Sollte das wirklich wie von dir behauptet funktionieren (so wie diverse Andere es von GC auch behaupteten) mag es tatsächlich eine gute Sache sein.
    Mal testen.


    Ich fragte, ob ARC ein GC-Abklatsch wäre, der genauso wenig taugt wie das Original.
    Ich sprach nicht davon, dass ARC ein GC sei. Eventuell mag dir aufgefallen sein, dass ich seit ungefähr einem Jahr hauptsächlich mit ARC arbeite, weil es eben kein Drecks-GC ist.
    Damals™ war mir das in der Tat noch nicht klar.
    Deshalb fragte ich, anstatt (wie von dir unterstellt) zu behaupten.
    «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
  • [2] übertragen: minderwertige Nachahmung eines Gegenstandes oder eines Konzeptes, das eine große Ähnlichkeit zum Original aufweist

    Und die Frage bezog sich offenkundig auf die Durchsetzung, nicht auf die Natur.

    Aber ist auch nicht wichtig. Wchtig ist, dass man nirgendwo bei ARC retain, release, autorelease kennen 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"?