在数组之间传递项时的内存管理问题

时间:2011-02-22 21:00:21

标签: iphone objective-c memory-management

我试图通过调用此函数getNextRandomItem在三个不同位置之间移动一组字符串。这是我第一次调用它时,但第二次出现访问错误。你能解释一下我做错了吗?

新商品:binNew(NSMutable Array) - >当前项目(NS字符串) - >旧项目:binOld(NSMutable Array)

-(NSString *) getNextRandomItem {
    if (binNew.count > 0){
        if (currentItem) {
            [binUsed addObject:currentItem];
        }

        int r = floor(arc4random() % binNew.count);
        currentItem = [binNew objectAtIndex:r];
        [binNew removeObjectAtIndex:r];
        return currentItem;
    }
    return @"No more items!";
}

3 个答案:

答案 0 :(得分:0)

这一行

currentItem = [binNew objectAtIndex:r];

应该是

currentItem = [[[binNew objectAtIndex:r] retain] autorelease];

当您使用[binNew removeObjectAtIndex:r]从容器中删除对象时,它会收到release消息而没有retain - 它会导致无效指针(因为它指向已释放的对象)。 / p>

答案 1 :(得分:0)

从阵列中删除r时必须保留r。现在你删除它并将其指针设置为currentItem。保留计数应该为0,这可能会导致错误。你有两个选择。

1)在界面中添加一个属性:

@property (retain) NSString *currentItem;

并将其添加到您的实现中

@synthesize currentItem;

然后使用

self.currentItem = ...

而不是

currentItem = ...

2)使用正确的内存管理。请参阅更改的代码:

-(NSString *) getNextRandomItem {
    if (binNew.count > 0){
        if (currentItem) {
            [binUsed addObject:currentItem];
            [currentItem release]; //See here
            currentItem = nil; //See here
        }

        int r = floor(arc4random() % binNew.count);
        currentItem = [[binNew objectAtIndex:r] retain]; //See here
        [binNew removeObjectAtIndex:r];
        return currentItem;
    } else {
       [currentItem release];
       currentItem = nil;
    }
    return @"No more items!";
}

注意,目前您从未将currentItem设置为nil。你应该这样做。

答案 2 :(得分:0)

-(NSString *) getNextRandomItem {
    if (binNew.count > 0){
        if (currentItem) {
            [binUsed addObject: currentItem];
            [currentItem release]; //here
            currentItem = nil;//not really necessary
        }

        int r = floor(arc4random() % binNew.count);
        currentItem = [[binNew objectAtIndex:r] retain]; //and here
        [binNew removeObjectAtIndex:r];
        return currentItem;
    }
    return @"No more items!";
}