2 Stimmen

Spezifischere, allgemeine Objective-C-Speicherverwaltung

Nach allem, was ich über die Speicherverwaltung von Objective-C gelesen habe, klingt sie unglaublich einfach. Um es mit den Worten aller zu sagen: "Gib frei, was immer du zuweist, behalte oder kopiere". Aber ich denke, es gibt einige spezifischere Fälle, die nicht so eindeutig sind. Im Folgenden finden Sie einige Beispiele. Was ist die richtige Vorgehensweise für jede Situation:

SITUATION #1:

Foo *foo = [[foo alloc] init];
Foo *fooToo = [[[foo alloc] init] autorelease];

foo = fooToo;

Muss foo freigegeben werden, bevor es fooToo zugewiesen wird?

SITUATION #2 Ich scheine eine Menge Abstürze zu bekommen, wenn ich Dinge tue wie: (.h und .mashed zusammen für Bequemlichkeit)

Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;

-(id)init{
self = [super init];
}

-(void)dealloc{
[super dealloc];
[foo release];
}

Mir wird ständig gesagt, "immer in dealloc freigeben, was Sie eine Retain-Eigenschaft für setzen". Aber dies wird abstürzen, wenn getan, wie ich gezeigt habe.

SITUATION #3 Eine ähnliche Situation, die ebenfalls zum Absturz führt: (.h und .mashed zusammen für Bequemlichkeit)

Foo *foo;
@property (nonatomic, retain) Foo *foo;
@synthesize foo;

-(id)init{
self = [super init];
self.foo = nil;
}

-(void)dealloc{
[super dealloc];
[foo release];
}

aus irgendeinem Grund, wenn mein Code macht es bis zu dealloc, foo ist nicht == nil.

SITUATION #4 Zum Schluss noch eine Frage: Welchen allgemeinen Denkprozess verwenden die Menschen bei der Entscheidung zwischen

 self.foo = bar;

y

 foo = bar;

wenn foo wie in den oben genannten Fällen deklariert wird? Ist self.foo nur eine andere Art der Codierung:

foo = [bar retain] ;

6voto

notnoop Punkte 57727

Situation #1:

Ja, Sie müssen die foo bevor Sie den Bezug zu ihr verlieren. Da Sie ihn zugewiesen haben, sind Sie für seine Freigabe verantwortlich. Wenn Sie ihn neu zuweisen foo bevor Sie es freigeben, können Sie es nicht mehr freigeben!

Situation #2:

Die ordnungsgemäße Umsetzung der dealloc ist:

- (void)dealloc {
    [foo release];
    [super dealloc];
}

El dealloc Methode muss die Super's dealloc Methode und nicht die release Methode. Außerdem müssen Sie die Felder zuerst freigeben, bevor Sie [super dealloc]

Situation #3: Gleiche Situation wie Situation 2.

Situation #4:

Ich bevorzuge immer die Verwendung von self.foo = bar da es die folgenden Schritte bei Bedarf automatisch durchführt:

  1. Freisetzung von foo
  2. Beibehaltung bar
  3. Zuweisung von foo a bar

Die Aufgaben foo = bar y foo = [bar retain] nicht das vorherige Objekt von foo .

4voto

bbum Punkte 161596

Halt, stopp! Msaeeds Antwort ist zeilenweise richtig, unterschlägt aber das eigentliche Problem.

Entweder denken Sie nicht wie ein Computer oder Sie nehmen an, dass viel zu viel Magie pro Codezeile.

Verstehen Sie das bitte nicht als Beleidigung - es ist ein sehr leicht zu begehender Fehler, den so gut wie jeder Programmierer macht, wenn er neu in einer Umgebung ist (ich habe einige wirklich fantastische magische Annahmen gemacht, als ich 1989 mit Objective-C anfing).

Lassen Sie uns die Situationen noch einmal überdenken.

SITUATION #1: ... irrelevanten Code löschen ...

foo = fooToo;

Dies ist eine einfache Aufgabe. Was auch immer foo die davor enthalten ist - in Ihrem Fall ein Verweis auf ein Objekt - wird nun durch den Wert von fooToo . Es gibt keine Magie. Es werden keine zusätzlichen Methoden oder Codezeilen ausgeführt.

Wenn foo einen Verweis auf ein zurückgehaltenes Objekt vor dieser Codezeile enthielt. Der Verweis wird überschrieben. Wenn Sie release foo bevor Sie den Verweis überschreiben, tun Sie dies, aber das hat nichts mit der Zuweisung zu tun.

SITUATION #2: ... irrelevanten Code löschen ...

-(void)dealloc{ [super dealloc]; [foo release]; }

Spielen Sie Computer; Sie bitten super zu deallocieren und nehmen dann an, dass eine Instanzvariable gültig ist, nachdem super deallociert wurde. Schlechte Nachrichten. Bumm.

Hier gibt es keine Magie. foo ist eine Referenz über self auf die Instanzvariable. Die -dealloc vernichtet sich selbst und damit, foo ist nicht mehr gültig.

(Ich glaube, dass der statische Analysator dies erkennt, wenn nicht, sollte er es tun).

SITUATION #3:

Siehe #2. Dies ist genau das gleiche Problem. Sie greifen auf eine Instanzvariable einer Instanz zu, die nicht mehr gültig ist.

SITUATION #4:

self.foo = bar;

ist genau das Gleiche wie:

[self setFoo: bar];

(Abgesehen von irgendwelchen Setzer=Schwindeleien)

Der entscheidende Unterschied ist also, was die Implementierung - handgeschrieben oder @synthetisiert - von -setFoo: tut. In Ihrem Fall ist es retain s Bar. Das ist anders als foo = bar; in dem Sinne, dass keine Beibehaltung stattfindet; es ist lediglich eine Zuweisung der Referenz zu bar .

Ich würde Ihnen dringend empfehlen, die Dokumentation zur Einführung in Objective-C noch einmal zu lesen. Das wird Ihnen helfen. Ich möchte Sie aber auch ermutigen, einen Schritt zurückzutreten und genau zu überlegen, was die einzelnen Codezeilen in den oben genannten Situationen bewirken. Es gibt keine Magie und das tatsächliche Verhalten ist sehr einfach.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X