我有一个理解问题。给出了这种方法:
- (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
应用程序将崩溃并说它无法访问已发布的对象
不release
result
字符串工具会报告泄漏(NSPlaceholderString)。
我可以autorelease
在alloc
它的同一行,它可以解决问题(我目前正在我的应用程序中进行)。
如果我理解正确stringByAppendingString:
应创建一个自动释放的对象,以便可以释放“旧”结果。然后方法arrayWithObject:
应该copy
将对象放入数组中。所以我的想法是在将字符串复制到数组后释放它。
我是否遗漏了我的知识?
答案 0 :(得分: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
的方法,{{名称中包含1}},alloc
或retain
。释放您不拥有的此对象几乎肯定会在某些时候导致崩溃。您拥有的旧对象和应该发布的早先丢失了两行,并且在其位置释放其他内容将无济于事。
答案 1 :(得分:8)
result = [result stringByAppendingString:@"something"];
此行用新的自动释放字符串替换第一个分配的字符串。
所以第一个字符串泄露,第二个字符串不应该被释放。这解释了为什么取消注释释放线崩溃。