1

我用我的 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

你知道问题是什么吗?

4

4 回答 4

5

这是写得不好的二传手的典型问题。当对象本身是属性的后备 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。

于 2012-09-24T14:54:12.170 回答
1

它应该if (facVersion != _facVersion)在二传手。否则,如果您再次设置相同的对象,您的 setter 将释放它(导致对象被释放),之后您将无法使用它(保留):

- (void) setFacVersion:(NSString*)_facVersion
{
    if(facVersion != _facVersion) {
        [facVersion release];
        facVersion = [_facVersion retain];
    }
}

另外,您知道自动引用计数 (ARC)吗?

自动引用计数 (ARC) 是一种编译器功能,可提供 Objective-C 对象的自动内存管理。不必考虑保留和释放操作,ARC 允许您专注于有趣的代码、对象图以及应用程序中对象之间的关系。

于 2012-09-24T14:53:27.337 回答
0

您在调用保留之前释放它。

除非您在释放和保留之前比较指针,否则您应该使用以下内容:

- (void) setFacVersion:(NSString*)_facVersion
    [_facVersion retain];
    [facVersion release];
    facVersion = _facVersion;
}

这样,如果指针相同,正如您所演示的,您将不会崩溃。

或者只是让编译器为您合成设置器。

于 2012-09-24T14:53:04.067 回答
0

如果您将相同的对象传递给setFacVersion已设置的对象,它将首先释放它,然后尝试保留已释放(和释放)的对象。

于 2012-09-24T14:52:47.710 回答