2

我有一个理解问题。给出了这个方法:

- (NSArray*)test {
 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
 NSString *result = [[NSString alloc] initWithBytes:[data bytes] 
            length:[data length] 
             encoding:NSMacOSRomanStringEncoding];
 result = [result stringByAppendingString:@"something"];
 NSArray *arr = [NSArray arrayWithObject:result];
 //[result release];
 return arr;
}

如果我取消注释release应用程序会崩溃并说它无法访问已发布的对象。
通过 not releaseingresult字符串 Instruments 会报告泄漏 (NSPlaceholderString)。

我可以autorelease在同一行上alloc解决问题(我目前在我的应用程序中这样做)。

如果我理解正确,stringByAppendingString:应该创建一个自动释放的对象,以便可以释放“旧”结果。然后方法arrayWithObject:应该copy将对象放入一个数组中。所以我的想法是在将字符串复制到数组后释放它。

我的知识是否遗漏了什么或有什么问题?

4

2 回答 2

11

让我们逐行浏览您的代码。

- (NSArray*)test {
 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];

这将创建一个数据对象。你不拥有它,但它会在该方法的剩余时间内一直存在。到现在为止还挺好。

 NSString *result = [[NSString alloc] initWithBytes:[data bytes] 
                                             length:[data length] 
                                           encoding:NSMacOSRomanStringEncoding];

这将创建一个您拥有的字符串对象。同样,这里没问题——我们只需要稍后发布它。

result = [result stringByAppendingString:@"something"];

您丢弃对其中的字符串对象的引用result并存储一个您不拥有的新字符串对象。这是一个泄漏,因为您不能再释放原始字符串。此外,您正确地注意到新字符串可以被视为自动释放的对象 - 这意味着您不应该释放它。

NSArray *arr = [NSArray arrayWithObject:result];

与您的看法相反,这并没有复制任何内容。它仅保留对新字符串的引用并保留它。

//[result release];

此时您不应该释放result,因为它包含的对象不是您拥有的——您是从 获得的stringByAppendingString:,而不是从带有new、或其名称的方法alloc中获得的。释放这个不属于你的对象几乎肯定会在某个时候导致崩溃。您拥有并应该释放的旧对象在两行之前丢失了,并且在其位置释放其他东西也无济于事。retaincopy

于 2010-12-27T20:55:28.293 回答
8
result = [result stringByAppendingString:@"something"];

此行将第一个分配的字符串替换为新的自动释放字符串。

所以第一个字符串被泄露,第二个字符串不应该被释放。这解释了为什么取消注释发布行会崩溃。

于 2010-12-27T20:35:19.177 回答