Управление памятью при копировании объектов

Я знаю, что мой вопрос уже обсуждался на StackOverflow, но я обнаружил, что ответ не соответствует моим потребностям. Итак, вопрос:

NSMutableArray *firstArray = [[NSMutableArray alloc] initWithObjects: obj1,obj2,nil];
NSMutableArray *secondArray = [[NSMutableArray alloc] init];
secondArray = [firstArray mutableCopy];

какое количество сохранений для второго массива сейчас? 2 или 1? Должен ли я выпускать его дважды или только один раз? Сохраняет ли копирование или увеличение mutableCopy количество объектов COPYING (secondArray в этом событии)?


person Andrey Chernukha    schedule 08.11.2011    source источник


Ответы (2)


Вы никогда не должны заботиться об абсолютном количестве сохранений. Только то, что вы «сбалансированы», это означает, что для каждого alloc, new*, copy, mutableCopy и retain вам нужен соответствующий release или autorelease (то есть, когда не используется ARC).

Если вы примените это правило к каждой строке, вы увидите, что во второй строке есть alloc, но релиза нет. На самом деле, размещать экземпляр здесь абсолютно бесполезно, так как он вам все равно не интересен. Поэтому следует просто читать:

NSMutableArray *firstArray = [[NSMutableArray alloc] initWithObjects: obj1,obj2,nil];
NSMutableArray *secondArray = [firstArray mutableCopy];
// There is no third line.

Но давайте обсудим ваш исходный код и посмотрим, что произошло:

NSMutableArray *firstArray = [[NSMutableArray alloc] initWithObjects: obj1,obj2,nil];
NSMutableArray *secondArray = [[NSMutableArray alloc] init];
// secondArray points to a new instance of type NSMutableArray
secondArray = [firstArray mutableCopy];
// You have copied another array (created a new NSMutableArray
// instance) and have overwritten the pointer to the old array.
// This means that the instance allocated in line 2 is still there
// (was not released) but you don't have a pointer to it any more.
// The array from line 2 has been leaked.

В Objective-C мы часто говорим о владении: очень мало методов, которые делают вас «владельцем» объекта. Это:

  • alloc
  • new*, as in newFoo
  • copy и mutableCopy
  • retain

Если вы вызываете их, вы получаете объект, за который вы отвечаете. А это значит, что вам нужно вызвать соответствующее число release и/или autorelease на эти объекты. Например, у вас все в порядке, если вы сделаете [[obj retain] retain];, а затем [[obj autorelease] release];

person DarkDust    schedule 08.11.2011
comment
Я бы добавил, что у вас есть два объекта, которые принадлежат вам и должны быть освобождены на каком-то этапе. И вы правы - retainCount не имеет значения - беспокойтесь только о том, чтобы сбалансировать владение вызовами с освобождением вызовов. - person Abizern; 08.11.2011
comment
На самом деле secondArray был выделен и использован где-то далеко в коде. Я написал это во второй строке просто для удобства. Итак, если я правильно вас понял, чтобы избежать утечек памяти, я должен сначала выпустить secondArray, и это будет абсолютно правильно? - person Andrey Chernukha; 08.11.2011
comment
@AndreyChernukha: Вы освобождаете объект, на который указывает secondArray, только после того, как закончите с ним работать. release означает: Начиная с этой строки этот объект мне больше не понадобится; он может быть освобожден. autorelease означает: Скоро он мне больше не понадобится; но он должен оставаться в живых, по крайней мере, до тех пор, пока я не оставлю этот метод. (Это не на 100% правильно, но достаточно близко к истине, чтобы быть полезным) - person DarkDust; 08.11.2011

NSMutableArray *firstArray = [[NSMutableArray alloc] initWithObjects: obj1,obj2,nil];
NSMutableArray *secondArray = [[NSMutableArray alloc] init];
secondArray = [firstArray mutableCopy];

Происходит то, что вы создали утечку памяти. Вы только что потеряли ссылку, назначенную для secondArray, когда вы перезаписали ее mutableCopy для firstArray этой строкой.

secondArray = [firstArray mutableCopy];

Если вы затем дважды отпустите secondArray, программа рухнет, потому что вы перезапустите изменяемый массив, назначенный

secondArray = [firstArray mutableCopy];

Что вам нужно сделать, так это убедиться, что вы не перезаписываете сохраненные ссылки по ошибке, и баланс сохраняется с выпусками.

person futureelite7    schedule 08.11.2011