NSString 释放问题

Posted

技术标签:

【中文标题】NSString 释放问题【英文标题】:NSString release problem 【发布时间】:2011-06-03 06:03:30 【问题描述】:

在测试一些代码时,我遇到了一个问题。听到的是我的代码和日志。

(IBAction) DynamicBtnClicked:(id)sender 

 NSString *strLog = [[NSString alloc] initWithString:@"SubView Index is..."];
 NSLog(@"initialized strLog address is = %p, retainCount = %d", strLog, [strLog retainCount]);
 if ([self.view.subviews count] > 0) 
     for (int i = 0 ; i < [self.view.subviews count] ; i++) 
         UIView *tmpView = [self.view.subviews objectAtIndex:i];
         strLog = [strLog stringByAppendingFormat:@"%d view`s index = %d, tag = %d", i, i,[tmpView tag]];
         NSLog(@"appended strLog address is = %p, retainCount = %d", strLog, [strLog retainCount]);
     
 

 NSLog(@"after appended strLog address is = %p, retainCount = %d", strLog, [strLog retainCount]);    
 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:strLog delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
 [alert show];
 [alert release];

 NSLog(@"after using strLog address is = %p, retainCount = %d", strLog, [strLog retainCount]);
 [strLog release];

下面是日志

2011-06-03 14:36:11.038 MakeViewUsingCode[3918:40b] initialized strLog address is = 0x45c4, retainCount = 2147483647
2011-06-03 14:36:11.039 MakeViewUsingCode[3918:40b] appended strLog address is = 0x9c028d0, retainCount = 1
2011-06-03 14:36:11.040 MakeViewUsingCode[3918:40b] appended strLog address is = 0x9c021b0, retainCount = 1
2011-06-03 14:36:11.041 MakeViewUsingCode[3918:40b] after appended strLog address is = 0x9c021b0, retainCount = 1
2011-06-03 14:36:11.081 MakeViewUsingCode[3918:40b] after using strLog address is = 0x9c021b0, retainCount = 3
2011-06-03 14:36:11.087 MakeViewUsingCode[3918:40b] *** -[CFString release]: message sent to deallocated instance 0x9c021b0
dlopen(/Developer/Library/Xcode/PrivatePlugIns/DebuggerFoundation.ideplugin/Contents/Resources/DebuggerIntrospectionSupport.dylib, 0x0000000A)
dyld: loaded: /Developer/Library/Xcode/PrivatePlugIns/DebuggerFoundation.ideplugin/Contents/Resources/DebuggerIntrospectionSupport.dylib
Current language:  auto; currently objective-c

我知道,我的代码中存在内存泄漏,但这不是真正的问题。(这是故意的。)

真正的问题是,当我运行我的代码时,会发生 EXC_BAD_ACCESS 运行时错误。

在我的代码中,我向接收者发送了一条消息以释放一次,但日志显示错误的原因是 NSString 对象的实例已被释放!

如果我向接收者发送消息两次释放,第一个位置在哪里?

谁能告诉我它在哪里?

谢谢。

【问题讨论】:

【参考方案1】:

不要太依赖retainCount。它们可能具有误导性。只要坚持内存管理规则,你就会做得很好。这里的问题是这一行,

strLog = [strLog stringByAppendingFormat:@"%d view`s index = %d, tag = %d", i, i,[tmpView tag]];

完成此操作后,strLog 指向一个自动释放的字符串。您尚未声明对此字符串的所有权,但您仍会在方法结束时释放它。所以想象一下它被创建一次并发布两次。那是你的问题。如果您只想将字符串附加到您创建的实例中,则必须使用NSMutableString

【讨论】:

非常感谢!是的,我应该考虑所有权!再次感谢!【参考方案2】:

当您在循环中第一次将该新字符串分配给 strlog 时,您将丢失对第一个字符串的引用。

NSString *strLog = [[NSString alloc] initWithString:@"SubView Index is..."];
for (int i = 0 ; i < [self.view.subviews count] ; i++) 
     // since you're not releasing the current reference, it's replaced with 
     // the following reference and thus leaked
     strLog = [strLog stringByAppendingFormat:@"%d view`s index = %d, tag = %d", i, i,[tmpView tag]];

相信 stringByAppendingFormat 返回一个自动释放的 NSString。如果是这种情况,我怀疑您看到的错误是因为您两次释放了对 strLog 的最后一个引用(创建对象时的隐式自动释放和方法结束时的显式释放)。

【讨论】:

以上是关于NSString 释放问题的主要内容,如果未能解决你的问题,请参考以下文章

NSString - stringWithFormat 自动释放

文字 NSString 是自动释放还是需要释放?

NSString 释放问题

保留和释放 nsstring

NSString 在时间之前被释放

NSString版本