2015-04-27 5 views
8

Ich habe ARC ausgeschaltet.Warum kein Speicherleck für: @property (copy) NSString * name, wenn ich es nicht in Dealloc freigeben?

Ich habe eine Eigenschaft in einer Klasse wie folgt erklärt:

@property(copy) NSString* name 

I gesetzt name mit einem konstanten string:

[greeter setName:@"Jane"]; 

ich dealloc für meine Klasse wie folgt umgesetzt:

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

Ich erwartete, dass es ein Memo geben würde ry leak, weil ich name nicht freigegeben habe. Ich verwende Xcode 6.2 und Product>Analyze identifiziert keine Lecks, und auch nicht Instrumente: Product>Profile, choose Leaks, hit the red Record button.

ist hier der entsprechende Code:

// 
// Greeter.h 
// Flashlight2 
// 

#import <Foundation/Foundation.h> 

@interface Greeter : NSObject 

@property(copy) NSString* name; 

-(NSString*)description; 
-(void)dealloc; 


@end 

....

// 
// Greeter.m 
// Flashlight2 
// 

#import "Greeter.h" 

@implementation Greeter 


-(NSString*)description { 
    NSString* msg = [[NSString alloc] initWithString:@"I am a Greeter"]; 
    return [msg autorelease]; 
} 

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

@end 

...

@implementation AppDelegate 


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

    // Override point for customization after application launch. 

    Greeter* greeter = [[Greeter alloc] init]; 
    [greeter setName:@"Jane"]; //constant string in memory for life of program 

    NSLog(@"%@", greeter); 
    [greeter release]; 


    return YES; 
} 

Nach einer Weile darüber nachzudenken, die einzige Erklärung, die ich kann kommen, ist, dass die name setter nicht tatsächlich Kopieren Sie die Konstantenzeichenfolge. Es sieht so aus, als ob Obj-C die Eigenschaft the string being assigned einer Eigenschaftsprüfung unterzieht, und weil es eine konstante Zeichenkette ist, ordnet Obj-C (the-pointer-to-the-constant-string) nur the-pointer-to-the-constant-string der name-pointer zu. Geht so etwas weiter?

+0

Das hängt nicht mit Ihrer Frage zusammen, aber mit einem Tag von ios8 nehme ich an, dass Sie sich nicht mit altem Code vor dem ARC beschäftigen, also bin ich neugierig, warum Sie ARC ausschalten möchten? – Rog

+3

@Rog, um über Speicherverwaltung zu lernen. – 7stud

+0

Yup, das ist der einzige gute Grund, den ich mir vorstellen konnte :) – Rog

Antwort

10

Hier arbeiten zwei Optimierungen, die zusammen dieses Ergebnis verursachen.

Erstens: NSString-Literale werden in einem speziellen Segment der Binärdatei gespeichert und nicht zur Laufzeit zugewiesen. Sie ignorieren Retain und Release und werden niemals zugewiesen oder freigegeben.

Zweitens: Das Kopieren eines unveränderlichen NSString (einschließlich eines String-Literals) wird nur beibehalten, weil die Kopie garantiert immer identisch mit dem Original wäre. (Dies wird durch Überschreiben der Methoden -ezugen und -freigabe in der privaten NSString-Unterklasse erreicht)

In Ihrem Szenario wird die Kopie also zu einem Retain, der Retain wird ignoriert, und die Aufhebung der Zuordnung würde nicht passieren, selbst wenn Sie hat die Saite in dealloc korrekt freigegeben.