#objective-c #memory-management #copy #retaincount
#objective-c #управление памятью #Копировать #сохранить количество
Вопрос:
Я знаю, что мой вопрос уже обсуждался в StackOverflow, но я нашел ответ неполным для моих нужд. Итак, вопрос в том:
NSMutableArray *firstArray = [[NSMutableArray alloc] initWithObjects: obj1,obj2,nil];
NSMutableArray *secondArray = [[NSMutableArray alloc] init];
secondArray = [firstArray mutableCopy];
какое количество сохранений для secondArray теперь? 2 или 1? Должен ли я выпускать его дважды или только один раз?
Сохраняется ли количество объектов КОПИРОВАНИЯ (в данном случае вторичного массива) при копировании или при увеличении изменяемой копии?
Ответ №1:
Вы никогда не должны заботиться об абсолютном количестве сохранений. Только то, что вы «сбалансированы», это означает, что для каждого 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*
, как вnewFoo
copy
иmutableCopy
retain
Если вы вызываете их, вы получаете объект, за который вы несете ответственность. И это означает, что вам нужно вызвать соответствующее количество release
и / или autorelease
для этих объектов. Например, все в порядке, если вы это сделаете [[obj retain] retain];
, а затем [[obj autorelease] release];
Комментарии:
1. Я бы добавил, что у вас есть два объекта, которые принадлежат и должны быть освобождены на каком-то этапе. И вы правы —
retainCount
это неважно — беспокоитесь только о балансировке вызовов владения с вызовами освобождения.2. На самом деле secondArray был выделен и использован где-то далеко в коде. Я написал это во второй строке просто для удобства. Итак, если я правильно вас понял, чтобы избежать утечек памяти, я должен сначала выпустить secondArray, и это было бы абсолютно справедливо?
3.@AndreyChernukha: Вы освобождаете объект, на который указывает
secondArray
, только после того, как закончите с ним.release
означает: начиная с этой строки, мне больше не понадобится этот объект; он может быть освобожден.autorelease
означает: Скоро мне это больше не понадобится; но он должен оставаться активным, по крайней мере, до тех пор, пока я не оставлю этот метод. (Это не на 100% правильно, но достаточно близко к истине, чтобы быть полезным)
Ответ №2:
NSMutableArray *firstArray = [[NSMutableArray alloc] initWithObjects: obj1,obj2,nil];
NSMutableArray *secondArray = [[NSMutableArray alloc] init];
secondArray = [firstArray mutableCopy];
Происходит то, что вы создали утечку памяти. Вы только что потеряли ссылку, присвоенную secondArray, когда перезаписали ее изменяемой копией firstArray с помощью этой строки.
secondArray = [firstArray mutableCopy];
Если вы затем дважды запустите secondArray, программа завершится сбоем, потому что вы переопределяете изменяемый массив, назначенный
secondArray = [firstArray mutableCopy];
Что вам нужно сделать, так это убедиться, что вы не перезаписываете сохраненные ссылки по ошибке, и баланс сохраняется с выпусками.