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

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

我关闭了 ARC。

我在 class 中有一个 属性 声明如下:

@property(copy) NSString* name

我用常量字符串设置name

[greeter setName:@"Jane"];

我像这样为我的 class 实现了 dealloc

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

我预计会发生内存泄漏,因为我没有释放 name。我正在使用 Xcode 6.2,Product>Analyze 没有发现任何泄漏,Instruments 也没有: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

.....

//
//  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;
}

想了想,我唯一能想到的解释是name setter实际上没有复制常量字符串。似乎 Obj-C 对 the string being assigned 和 属性 进行了类型检查,因为它是一个常量字符串,Obj-C 只是将 (?) the-pointer-to-the-constant-string 分配给 name-pointer.有这样的事情吗?

这里有两个优化组合导致了这个结果。

首先:NSString 文字存储在二进制文件的特殊段中,而不是在运行时分配。它们忽略保留和释放,并且永远不会分配或释放。

其次:复制不可变的 NSString(包括字符串文字)而不是只保留它,因为副本将保证始终与原始版本相同。 (这是通过覆盖私有 NSString 子类中的 -copyWithZone: 方法实现的)

所以在你的场景中,复制变成了保留,保留被忽略,即使你在 dealloc 中正确释放字符串,也不会发生释放。