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

时间:2015-04-27 21:10:53

标签: objective-c memory-leaks ios8

我关闭了ARC。

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

@property(copy) NSString* name

我使用常量字符串设置name

[greeter setName:@"Jane"];

我为我的班级实施了dealloc

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

我预计会有内存泄漏,因为我没有发布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

...

//
//  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。是这样的吗?

1 个答案:

答案 0 :(得分:10)

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

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

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

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