开发者

Memory management issues when passing items between arrays

I'm attempting to move a group of strings between three different places by calling this function getNextRandomItem. This works the first time I call it, but then I get an access error the second time. Can you explain what I'm doing wrong?

Ne开发者_StackOverflow社区w Items:binNew (NSMutable Array) -> Current Item (NS String) -> Old Items: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!";
}


You have to retain r when it is removed from the array. Now you remove it and set its pointer to currentItem. The retain count should become 0 so that probably will cause the error. You have two options.

1) Add a property in your interface:

@property (retain) NSString *currentItem;

and add this to your implementation

@synthesize currentItem;

then use

self.currentItem = ...

instead of

currentItem = ...

2) Use correct memory management. See altered code:

-(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!";
}

Note currently you never set your currentItem to nil. You should do that.


This line

currentItem = [binNew objectAtIndex:r];

should be

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

When you remove object from container with [binNew removeObjectAtIndex:r], it receives release message and without retain-ing it, you get an invalid pointer (because it points to released object).


-(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!";
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜