我使用Xcode启用了僵尸,以查找我的进程是否崩溃到内存泄漏。这是一段代码:
- (NSString *)facVersion
{
return facVersion;
}
- (void) setFacVersion:(NSString*)_facVersion
{
if(facVersion != nil) [facVersion release];
facVersion = [_facVersion retain];
}
现在我打电话
NSLog(@"%@", facVersion);
[self setFacVersion:facVersion];
代码与消息
崩溃[CFString retain]:发送给deallocated的消息
你知道问题是什么吗?
答案 0 :(得分:4)
这是编写错误的setter的典型问题。当对象本身是属性的后备ivar的最后一个所有者时,将属性分配给自身会导致释放有效地释放对象,然后保留在同一个已释放的对象上。您可以通过两种方式解决此问题。检查要分配的对象与属性的当前值是否相同,或者先保留并仅在之后释放。总而言之,解决方案之一:
- (void) setFacVersion:(NSString*)_facVersion
{
if (facVersion == _facVersion) return;
[facVersion release];
facVersion = [_facVersion retain];
}
解决方案二:
- (void) setFacVersion:(NSString*)_facVersion
{
[_facVersion retain];
[facVersion release];
facVersion = _facVersion;
}
顺便说一句,在释放之前检查对象不是nil
是多余的。 Objective-C不是Java。
答案 1 :(得分:1)
它应该是setter中的if (facVersion != _facVersion)
。否则,如果再次设置相同的对象,您的setter将释放它(导致对象被释放),之后您不能使用它(保留):
- (void) setFacVersion:(NSString*)_facVersion
{
if(facVersion != _facVersion) {
[facVersion release];
facVersion = [_facVersion retain];
}
}
另外,你知道Automatic Reference Counting (ARC)吗?
自动引用计数(ARC)是一种提供的编译器功能 Objective-C对象的自动内存管理。而不是拥有 考虑保留和释放操作,ARC允许您 专注于有趣的代码,对象图和 应用程序中对象之间的关系。
答案 2 :(得分:0)
如果将同一个对象传递给已经设置的setFacVersion
,它将首先释放它,然后尝试保留已释放(和解除分配)的对象。
答案 3 :(得分:0)
您在致电保留之前已将其释放。
除非你在发布和保留之前比较指针,否则你应该使用类似的东西:
- (void) setFacVersion:(NSString*)_facVersion
[_facVersion retain];
[facVersion release];
facVersion = _facVersion;
}
这样,如果指针是相同的,就像你演示的那样,你就不会崩溃。
或者让编译器为你合成setter。