当用户点击“保存”按钮时,我运行了以下代码:
- (IBAction) onSaveChangesClick:(id)sender {
NSMutableString *newGroups = [[NSMutableString alloc] init];
for (int i = 0; i < [self.isInGroupArr count]; i++) {
if ([[self.isInGroupArr objectAtIndex:i] boolValue] == YES) {
[newGroups appendString:[[AppDelegate arrayGroups] objectAtIndex:i]];
[newGroups appendString:@","];
}
}
// remove last : ","
if ([newGroups length] > 0)
newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]];
self.contact.groups = newGroups;
[newGroups release];
//[[self navigationController] popViewControllerAnimated:YES];
}
self.IsInGroups
是BOOL
数组,arrayGroups
是(NSString *) array
,其中包含组名。
我想将newGroups
字符串添加到arrayGroups[i]
if (IsInGroups[i] == YES)
。
这段代码生成EXC_BAD_ACCESS
。为什么?
感谢。
答案 0 :(得分:2)
newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]];
此行生成泄漏,然后是崩溃的原因。
执行此操作后,您不再拥有alloc / inited可变字符串的引用,并且您有一个自动释放的字符串。所以在该字符串上调用release会导致某个地方出现双重释放。
编辑:使用解决方案
最简单的解决方案:不要添加最后一个','。
for (int i = 0; i < [self.isInGroupArr count]; i++) {
if ([[self.isInGroupArr objectAtIndex:i] boolValue] == YES) {
[newGroups appendString:[[AppDelegate arrayGroups] objectAtIndex:i]];
if (i != ([self.isInGroupArr count] - 1))
[newGroups appendString:@","];
}
}
不是很优雅,但非常有效(尽管每次都可以避免计算)。
答案 1 :(得分:1)
在这里,您可以创建NSMutable字符串的自动释放实例。
newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]];
所以你不应该释放它,一切都会好的。
以下是改进的代码:
- (IBAction) onSaveChangesClick:(id)sender {
NSMutableString *newGroups = [[[NSMutableString alloc] init] autorelease];
for (int i = 0; i < [self.isInGroupArr count]; i++) {
if ([[self.isInGroupArr objectAtIndex:i] boolValue] == YES) {
[newGroups appendString:[[AppDelegate arrayGroups] objectAtIndex:i]];
[newGroups appendString:@","];
}
}
// remove last : ","
if ([newGroups length] > 0)
newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]];
self.contact.groups = newGroups;
//[[self navigationController] popViewControllerAnimated:YES];
}
说明:
在这里你分配内存并保留它。
[[NSMutableString alloc] init]
[NSMutableString stringWithString:返回NSMutable字符串的自动释放实例,我们不应该释放它(它与[[[NSMutableString alloc] init] autorelease相同] + smth more)。并将它分配给变量newGroups(因此存储在此变量中的旧值丢失)
if([newGroups length]&gt; 0) newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]];
这里的newGroups是自动释放的,你释放它,它就会破坏它。但由于它是自动释放的,自动释放池会尝试再次释放它并获得异常(因为内存已经全部免费)
[newGroups release];
答案 2 :(得分:0)
你已经分配了一个字符串(NSMutableString * newGroups = [[NSMutableString alloc] init]; )
然后为其分配一个autorelease字符串(newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]]; )。
你永远不应该这样做。请参阅此博客 - http://andycodes.tumblr.com/post/947927280/difficult-bug-finally-solved
评论[newGroups release];并且代码应该可以正常工作。
同样总是设置NSZombieEnabled环境变量并再次运行代码,看一下崩溃日志,你会得到究竟是哪个对象导致崩溃。