1

当用户单击“保存”按钮时,我运行以下代码:

- (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.IsInGroupsBOOL数组,arrayGroups(NSString *) array保存组名。我想将newGroups字符串添加到arrayGroups[i]唯一的if (IsInGroups[i] == YES).

这段代码生成EXC_BAD_ACCESS. 为什么?

谢谢。

4

3 回答 3

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:@","];
    }
}

不是很优雅,但非常有效(尽管每次都可以避免计数)。

于 2011-03-02T11:38:25.287 回答
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];

}

解释:

  1. 在这里您分配内存并保留它。

    [[NSMutableString alloc] 初始化]

  2. [NSMutableString stringWithString: 返回自动释放的 NSMutable 字符串实例,我们不应该释放它(它与 [[[NSMutableString alloc] init] autorelease] + smth 的作用相同)。并将其分配给变量 newGroups(因此存储在此变量中的旧值丢失)

if ([newGroups length] > 0) newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]];

  1. 这里的 newGroups 是自动释放的,你释放它,它就会销毁。但是因为它是自动释放的,所以自动释放池会尝试再次释放它并获得异常(因为内存已经空闲)

    [新组发布];

于 2011-03-02T11:40:29.940 回答
0

您已经分配了一个字符串(NSMutableString *newGroups = [[NSMutableString alloc] init]; )

然后为其分配一个自动释放字符串(newGroups = [NSMutableString stringWithString:[newGroups substringToIndex:[newGroups length] - 1]]; )。

你永远不应该这样做。请参阅此博客 - http://andycodes.tumblr.com/post/947927280/difficult-bug-finally-solved

注释掉[newGroups release];并且代码应该可以正常工作。

还要始终设置 NSZombieEnabled 环境变量并再次运行代码,查看崩溃日志,您将准确了解导致崩溃的对象。

于 2011-03-02T11:42:48.340 回答