2009-08-18 13 views
3

Wenn ich ein Objekt in einer Methode, 'getASprocket' zuweisen und es so nennen, wird es hier ein Leck geben?Speicherverwaltung und Leistung

Sprocket *sprock = [Sprocket getASprocket]; 

// store this returned value as an ivar 
ivarSprock = [sprock retain]; 

// release the originally acquired object 
[sprock release]; 

Das Kettenrad Objekt wird auf diese Weise zugeordnet und zurückgegeben:

– (Sprocket *)getASprocket { 
    Sprocket *sprocket; 

    sprocket = [[Sprocket alloc] init]; 

    return [sprocket retain]; 
} 

Auch aus '[sprocket retain];' würde innerhalb der 'aSprocket' Methode 'return [sprocket autorelease];' schlechtere Performance Hit zu ändern?

+0

Es sieht aus wie Sie einen Tippfehler gemacht haben; Das "-" sollte ein "+" sein, da Sie es als Klassenmethode und nicht als Instanzmethode verwenden. – Michael

+0

@Michael, während Ihr Kommentar in den meisten Fällen korrekt ist, ist dies technisch korrekt, sogar mit einem "-" –

Antwort

0

sehen Sie bitte dieses gute Erklärung Seite Especially sub-page #7

jedes andere Speicherobjekt erstellt retain.sehen, so können, was wir haben:
in getASprocket:

sprocket = [[Sprocket alloc] init]; 

+1

return [sprocket retain]; 

+1

und auf Ihre Methode:

ivarSprock = [sprock retain]; 

+1

[sprock release]; 

-1

Was sollten wir tun? Nun, wir sollten die Sprock gehen lassen, indem sie es machen Autorelease:

return [[[Sprocket alloc] init] autorelease] 

oder in den Worten des reffered Link oben:

In den meisten Fällen sollte der Setter für eine Instanz Variable nur Autorelease das altes Objekt, und behalten Sie das neue. Sie stellen dann sicher, dass Sie es auch in Dealloc freigeben.

0

Sie sollten wahrscheinlich die memory management guide lesen. Es ist nicht lange und es ist eine sehr gesunde Lektüre.

return [sprocket retain]; 

zu:

In Bezug auf Ihre speziellen Fall, in getASprocket sollten Sie ändern

return [sprocket autorelease]; 

da der Anrufer des Verfahrens nicht verantwortlich für die Freigabe des Objekts sein sollte (es sei denn, er behält es selbst, offensichtlich).

Es geht auch nicht um Leistung überhaupt - es ist alles Speicherverwaltung.

0

All dies führt in der Tat zu Undichtigkeiten. Lassen Sie uns also den Referenzzähler Ihres Sprockets durchgehen, in getASprocket sagen Sie Sprocet alloc, das die Zählung erhöht und dann behält, was wiederum erhöht, dass Sie hier bei +2 sind, und dann im ersten Codeblock wieder +3 Wenn Sie dann +2 loslassen, haben Sie das Objekt mit einer Referenzzahl von +2 geleakt. Was Sie i s tun können

-(Sprocket*)getASprocket) 
{ 
    return [[[Sprocket alloc] init] autorelease] 
} 

dies hält den Referenzzähler bei 0

0

ein Leck in Ihrem getASprocket Es gibt: Methode.

sprocket = [[Sprocket alloc] init]; 
return [sprocket retain]; 

Sie behalten Ritzel zweimal, einmal mit alloc/init und einmal mit behalten, was Sie nicht tun möchten. Verwenden Sie

return [sprocket autorelease]; 

Auch sicher sein, iVarSprock auf Null zu setzen, bevor Sie Kettenrad lösen oder es wird zu einem zufälligen Speicher zeigen.

0

Obwohl technisch nicht inkorrekt, ist die getASprocket Methode im Gegensatz zu typischen Cocoa und Cocoa Touch Entwicklung. Wenn Sie nicht eine zusätzliche Logik in der Methode verfügen, würden Sie besser gedient dies zu tun:

ivarSprock = [[ Sprocket alloc ] init ]; 

// Other Code Here 

[ ivarSprock release ]; 
0

Als Nebenwirkung, wenn Sie in einer Anwendung besorgt über die Leistung sind, die Sache, die man auf den ersten Blick sollte und In erster Linie sind die Algorithmen, die Sie verwenden, um Ihre Software zu implementieren. Das wird in erster Linie die Leistung verbessern. Erst nachdem Sie starke Algorithmen implementiert haben, sollten Sie (falls erforderlich) zurückgehen und sich die kleineren Sorgen ansehen.

0

Angesichts der Art, wie Sie Ihre Methode geschrieben haben, gibt es tatsächlich ein Leck in Ihrem Code. Sie würden wollen, dass es schreiben, wie folgt aus (sonst „sprock“ mit einer Zahl von 1 behalten endet, und deshalb dealloc'd nicht):

+ (Sprocket *)getASprocket 
{ 
    return [[[Sprocket alloc] init] autorelease]; 
} 

behalten zählt, sind wirklich sehr einfach, sobald man den Dreh bekommen von es. Befolgen Sie diese Regeln:

  • von alloc oder copy hat erstellt Objekte einen Beibehaltungszähler von 1 (und muss freigegeben werden)
  • Angenommen, alle andere Objekte einen Beibehaltungszähler von 1 haben, sind aber Autoreleased (wie die oben Methode)
  • Retain Objekte, die Sie rund um
  • Release Objekte behalten möchten, wenn Sie in ihnen nicht mehr interessiert sind (nie Anruf dealloc selbst)

Die Verwendung von Autorelease-Pools wirkt sich zwar leicht auf die Leistung aus, macht die Arbeit jedoch wesentlich einfacher, da Sie die internen Implementierungsdetails der einzelnen Methoden nicht kennen müssen.