为什么没有内存泄漏:@property(copy)NSString*name,当我不在dealloc中释放它时?

7st*_*tud 8 memory-leaks objective-c ios8

我关掉了ARC.

我在这样声明的类中有一个属性:

@property(copy) NSString* name
Run Code Online (Sandbox Code Playgroud)

name用常量字符串设置:

[greeter setName:@"Jane"];
Run Code Online (Sandbox Code Playgroud)

dealloc为我的班级实现了这样的:

-(void)dealloc{
    [super dealloc];
}
Run Code Online (Sandbox Code Playgroud)

我预计会有内存泄漏,因为我没有发布name.我正在使用Xcode 6.2并且Product>Analyze没有识别任何泄漏,仪器也没有:Product>Profile, choose Leaks, hit the red Record button.

这是相关代码:

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

#import <Foundation/Foundation.h>

@interface Greeter : NSObject

@property(copy) NSString* name; 

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


@end
Run Code Online (Sandbox Code Playgroud)

....

//
//  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
Run Code Online (Sandbox Code Playgroud)

...

@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;
}
Run Code Online (Sandbox Code Playgroud)

在考虑了一段时间之后,我能想到的唯一解释是实际上name setter并没有复制常量字符串.似乎Obj-C 对属性进行了类型检查,因为它是一个常量字符串,Obj-C只是将(?)分配给.是这样的吗?the string being assignedthe-pointer-to-the-constant-stringname-pointer

Cat*_*Man 10

这里有两个优化组合起来导致这个结果.

第一:NSString文字存储在二进制文件的特殊段中,而不是在运行时分配.它们忽略保留和释放,并且从不分配或取消分配.

第二:复制不可变的NSString(包括字符串文字)而不是保留它,因为副本将保证始终与原始相同.(这是通过覆盖私有NSString子类中的-retain和-release方法来实现的)

因此,在您的方案中,副本将变为保留,保留被忽略,即使您在dealloc中正确释放字符串,也不会发生释放.