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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With