Проблемы управления памятью при передаче элементов между массивами - PullRequest
0 голосов
/ 23 февраля 2011

Я пытаюсь переместить группу строк между тремя разными местами, вызывая эту функцию 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 голосов
/ 23 февраля 2011

Вы должны сохранить 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 на ноль.Ты должен сделать это.

0 голосов
/ 23 февраля 2011
-(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 голосов
/ 23 февраля 2011

Эта строка

currentItem = [binNew objectAtIndex:r];

должно быть

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

Когда вы удаляете объект из контейнера с [binNew removeObjectAtIndex:r], он получает сообщение release и без retain -информации вы получаете недопустимый указатель (потому что он указывает на освобожденный объект).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...