为什么没有内存泄漏:@属性(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 中正确释放字符串,也不会发生释放。
我关闭了 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 中正确释放字符串,也不会发生释放。