如何处理@synthesized保留属性的释放?

问题描述 投票:0回答:4

我对 Objective-C 中的综合属性有一些疑问。完整列表如下,但基本问题是:编译器如何确保合成属性的 ivars 被正确释放,即使我的代码可能或可能不包含 dealloc 中的释放方法?

注意:我决定不将这些作为单独的问题发布,因为它们是如此密切相关,并且因为有一些现有的问题触及在个别问题上,而没有真正触及问题的核心。

有些类似的问题:


设置: 考虑一个具有单个属性的类:

@interface Person : NSObject
{
    NSString * name;
}
@property (nonatomic, retain) name;
@end

问题#1:最基本的情况:

@implementation Person
@synthesize name;
@end

通过此设置,我假设每当释放

name
对象时,
Person
都会自动释放。在我看来,编译器只是将
[name release]
插入到
dealloc
方法中,就像我自己输入的一样。这是正确的吗?


问题#2:如果我选择为此类编写自己的

dealloc
方法,并且省略对
[name release]
的调用,会泄漏吗?

@implementation Person
@synthesize name;
- (void)dealloc { [super dealloc]; }
@end

问题#3:如果我选择为此类编写自己的

dealloc
方法,并且我include
[name release]
的调用,这是否会导致双重释放,因为
@synthesize
已经采取了帮我照顾它吗?

@implementation Person
@synthesize name;
- (void)dealloc { [name release]; [super dealloc]; }
@end

问题#4:如果我选择为此类编写自己的属性访问器,但我编写自己的

dealloc
方法,
name
会被泄漏吗?

@implementation Person
@dynamic name;
- (void)setName:(NSString *)newName
{
    [newName retain];
    [name release];
    name = newName;
}
@end

问题#5:我有一种感觉(根据经验),上述场景中的任何一个都不会导致泄漏或双重发布,因为该语言的设计就是为了避免它们。当然,这提出了“如何?”的问题。编译器是否足够聪明,可以跟踪每种可能的情况?如果我要执行以下操作(请注意,这是一个可笑的示例,只是为了说明我的观点): void Cleanup(id object) { [object release]; } @implementation Person @synthesize name; - (void)dealloc { Cleanup(name); } @end

这会欺骗编译器在 
[name release]

方法中添加另一个

dealloc
吗?
    

objective-c memory-management properties
4个回答
58
投票
问题1:

不。

@synthesize

不会为您修改

-dealloc
。你必须自己
-release
name

问题2:

是的,它会泄漏。原因与 Q1 相同。

Q3:

不,它不会双重发布。原因与 Q1 相同。

Q4:

是的,它会泄漏。原因与 Q1 相同。

问题5:

不,它不会双重发布。原因与 Q1 相同。

您可以通过覆盖
-retain

-release
-dealloc
自行检查以报告发生的情况。

#import <Foundation/Foundation.h> @interface X : NSObject {} @end @implementation X -(oneway void)release { NSLog(@"Releasing %p, next count = %d", self, [self retainCount]-1); [super release]; } -(id)retain { NSLog(@"Retaining %p, next count = %d", self, [self retainCount]+1); return [super retain]; } -(void)dealloc { NSLog(@"Dealloc %p", self); [super dealloc]; } @end @interface Y : NSObject { X* x; } @property (nonatomic, retain) X* x; @end @implementation Y @synthesize x; - (void)dealloc { [x release]; [super dealloc]; } @end int main () { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; Y* y = [[Y alloc] init]; X* x = [[X alloc] init]; y.x = x; [y release]; [x release]; [pool drain]; return 0; }

在Q1、Q2和Q4中,
-retainCount

的最后一个

x
为1,因此存在泄漏,而在Q3和Q5中,最后一个
-retainCount
为0并且调用了
-dealloc
,因此不存在泄漏.
    


17
投票
Objective-C 属性文档

释放

声明的属性基本上采用 访问器方法的位置 声明;当你合成一个 属性,编译器只创建 任何缺少的访问器方法。有 与 dealloc 没有直接交互 方法—属性不是 自动为你释放。 然而,声明的属性确实 提供一种有用的交叉检查方法 你的 dealloc 的实现 方法:你可以查找所有 标头中的属性声明 文件并确保该对象 未标记分配的属性是 已释放,那些标记为分配的是 没有发布。

这基本上回答了您所有的问题。


8
投票

当您在

retain

语句中使用

@synthesize
setter 语义设置时,您要求编译器为您构建一个在对象上调用
retain
的 setter。不多不少。由于您要保留该对象(即使它是通过神奇地自动生成的代码),因此您必须释放它,并且在哪里释放它在
-(void)dealloc
中。
    


2
投票

© www.soinside.com 2019 - 2024. All rights reserved.