Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why no memory leak for: @property(copy) NSString* name, when I don't release it in dealloc?

I turned ARC off.

I have a property in a class declared like this:

@property(copy) NSString* name

I set name with a constant string:

[greeter setName:@"Jane"];

I implemented dealloc for my class like this:

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

I expected there would be a memory leak because I didn't release name. I'm using Xcode 6.2 and Product>Analyze does not identify any leaks, and neither does Instruments: Product>Profile, choose Leaks, hit the red Record button.

Here is the relevant 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;
}

After thinking about it for awhile, the only explanation that I can come up with is that the name setter doesn't actually copy the constant string. It seems like Obj-C does a type check on the string being assigned to the property, and because it's a constant string, Obj-C just assigns(?) the-pointer-to-the-constant-string to the name-pointer. Is something like that going on?

like image 757
7stud Avatar asked Apr 27 '15 21:04

7stud


1 Answers

There's two optimizations at work here that combine to cause this result.

First: NSString literals are stored in a special segment of the binary, rather than allocated at runtime. They ignore retain and release, and are never allocated or deallocated.

Second: Copying an immutable NSString (including a string literal) instead just retains it, because the copy would be guaranteed to always be identical to the original. (This is accomplished by overriding the -copyWithZone: method in the private NSString subclass)

So in your scenario, the copy turns into a retain, the retain is ignored, and the deallocation wouldn't happen even if you did properly release the string in dealloc.

like image 82
Catfish_Man Avatar answered Sep 21 '22 07:09

Catfish_Man