我对内存管理有疑问。
让我们从一个例子开始。假设我们有一个类如下。
@interface myClass : NSObject {
NSString *xyz;
}
@end
现在,请参阅实施。
@interface myClass : NSObject {
NSString *xyz;
}
@end
@implementation myClass
-(void)abc{
// xyz allocted here
}
-(void)pqr{
// retained or copied many times or may not a single time
}
-(void)mno{
// retained or copied many times or may not a single time
}
-(void)jpg{
// may be released more than one time or may be not
}
//-(void)dealloc{
// [xyz release];
// [super dealloc];
//}
//
//-(void)dealloc{
// if(xyz!=nil && [xyz retainCount]>0){ [xyz release]; xyz=nil; }
// [super dealloc];
//}
-(void)dealloc{
if(xyz!=nil){
while([xyz retainCount]>0)
[xyz release];
xyz=nil;
}
[super dealloc];
}
@end
在上面的代码中。我有三个dealloc函数。哪个更好?如果没有,请建议你的。
我很困惑,因为Objective C说,每次都必须释放对象=每次分配/保留。
但是大多数示例代码只有一个语句“[xyz release];”它不会造成内存泄漏吗?
答案 0 :(得分:12)
这是绝对错误的:
while([xyz retainCount]>0)
[xyz release];
xyz=nil;
retainCount
将永远不会返回0,因为只要您处于retainCount为1且对象被释放,运行时就会立即释放它,然后永远不会减少retainCount 。即使它确实减少了retainCount,该对象现在也被释放了。你怎么会问它什么是retainCount?
简而言之,您的设计是错误的。如果你无法跟踪你以更聪明的方式保留对象的频率,那么你将有内存泄漏并且很可能会因过度释放的对象而崩溃(这会导致你的应用程序崩溃)
如果你绝对无法改变你的代码(如果你说你不能改变我就不相信你),那么你想要保留第二个整数ivar,表明你保留了多少次{{1然后使用 来确定应该释放它的次数。 (但是,这应该是一个绝对的最后努力,因为如果你没有在30秒内完成这项工作,就会发生Armaggeddon。你应该首先重构你的代码。)
此外,您忘记了xyz
方法中对[super dealloc]
的来电。
答案 1 :(得分:4)
- (void)dealloc {
[xyz release];
[super dealloc];
}
...是正确的版本。在Objective-C中,通常不应使用retainCount
方法。
如果你想要非常安全,你也可以写:
- (void)dealloc {
[xyz release], xyz = nil;
[super dealloc];
}
答案 2 :(得分:1)
我的想法是myClass有一个成员变量(在你的例子中是xyz)。当创建myClass对象时,它应该通过仅向保留计数添加1来创建(或获取对xyz的引用)(无论是通过保留还是其他方式取决于具体情况)。
在每种方法中保留xyz并再次释放它并不是一个好主意。因此,在每个方法结束时,本地对象应该不再拥有xyz,而不是在方法开头时。
当dealloc被调用时,只有那个单独的retain hold应该保留在xyz上(就myClass对象而言),所以单次调用release就足够了。在retainCount为零之前发布并不是一个好主意,因为某个地方的某个对象可能正在使用它。
要直接回答您的问题,请使用此dealloc:
-(void)dealloc{
[xyz release];
}
答案 3 :(得分:1)
在poperty声明中保留的对象需要在dealloc方法中释放。所以如果你宣布
@property(nonatomic, retain)NSString xyz;
,
你需要以dealloc发布
-(void)dealloc{
[xyz release];
[super dealloc]
}
在方法中最后一次使用该对象后,应立即释放任何其他已分配的内存。
所以如果你在
中分配xyz-(void)abc{
// xyz allocted here
}
然后你会在同一方法结束时释放它。
-(void)abc{
// xyz allocted here
// do something with xyz
//release xyz
示例:
-(void)abc{
xyz=[[NSString alloc]init];//this may not be what you are following, but i just meant allocating memory
// do something with xyz
[xyz release]
//release xyz
在这种情况下,您无需在dealloc方法中释放它。
同样不是如果你是声明xyz并对其进行修饰的属性,你不应该在你的方法中分配它,也不应该发布
答案 4 :(得分:0)
while([xyz retainCount]==0)
[xyz release];
应为> 0
,否则-release
不会执行。即便如此,解除xyz
这样的做法也是不好的做法,因为xyz
可能仍归其他人所有。
您应该只分配xyz
一次,如果您-copy
要替换xyz
,则始终-release
旧的xyz
。始终遵循Cocoa内存管理规则。
如果您确实需要对xyz
采用多个所有权,并使用单独的整数ivar来记录您保留-release
的次数,那么您拥有正确的-dealloc
个数字{{1}}。