#iphone #ios #memory-management #memory-leaks
#iPhone #iOS #управление памятью #утечки памяти
Вопрос:
В настоящее время у меня есть категория NSMutableArray, которая создает NSMutableArray, распространяемый с помощью NSNulls. Когда я запускаю этот код в Инструментах, он сообщает мне, что у меня здесь утечка (прочитайте комментарий, чтобы узнать, где)
#import "NSMutableArray NSNull.h"
@implementation NSMutableArray (NSNull)
-(id)initWithNullCapacity:(int)capacity{
self = [super init];
if (self) {
//Leak on [self init]
NSMutableArray *array = [self init];
for (unsigned i = 0; i < capacity; i )
{
[array addObject:[NSNull null]];
}
self = array;
}
return self;
}
Редактировать:
Здесь я вызываю метод:
#import "TWVStatData.h"
#import "NSMutableArray NSNull.h"
@implementation TWVStatData
@synthesize creationTime;
@synthesize graphs;
@synthesize elements;
@synthesize type;
-(id)init{
if(self == [super init]){
type = -1;
creationTime = [[NSDate alloc] init];
graphs = [[NSMutableArray alloc] initWithNullCapacity:3];
elements =[[NSMutableArray alloc] init];
}
return self;
}
Ответ №1:
Это будет сложно, в первую очередь из-за того, как NSArray
работает под ним. Я бы рекомендовал сделать это:
- (id)initWithNullCapacity:(NSUInteger)capacity {
NSMutableArray *nulls = [NSMutableArray array];
for (NSUInteger i = 0; i < capacity; i ) {
[nulls addObject:[NSNull null]];
}
return [self initWithArray:nulls];
}
Я думаю, что проблема связана с присвоением self
, хотя я не уверен в этом. NSArray
выполняет некоторые сложные оптимизации под капотом, и поэтому я бы не вызывал NSArray
инициализатор до тех пор, пока после вас все ваши данные не будут готовы к отправке.
Комментарии:
1. Когда я запускаю ваш код в Инструментах, я получаю ошибку при возврате строки [self initWithArray: nulls]; После проб и ошибок мне удалось исправить это с помощью реализации, которую я опубликовал в качестве ответа.
2. @Cyprian тогда вы делаете что-то неправильно, потому что, когда я использую это изолированным образом, оно отлично работает без утечек.
3. 1 выглядит неплохо, но я полагаю, что цена удерживает в памяти 2 массива вместо одного на некоторое время, не то чтобы я думаю, что это вызовет какие-либо реальные последствия
Ответ №2:
Вы не создаете подкласс NSMutableArray, просто добавляя категорию, поэтому вызов [super init] вызовет NSArray, а не инициализатор NSMutableArray, независимо от того, выполняет ли он, который я бы вызвал на всякий случай, если он делает что-то важное.
Также, как упоминал Равин, установка self = без вызова [self release] сначала приведет к утечке предыдущего объекта, который был возвращен из вызова alloc на один уровень выше в стеке вызовов.
Это то, что вы должны сделать:
-(id)initWithNullCapacity:(int)capacity
{
self = [self initWithCapacity:capacity];
if (self)
{
for (int i = 0; i < [self count]; i )
{
[self addObject:[NSNull null]];
}
}
return self;
}
Комментарии:
1. Когда я делаю то, что вы предлагаете, инструменты сообщают мне, что у меня утечка в строке self = [self initWithCapacity:емкость];
2. @Cyprian не могли бы вы опубликовать код, использующий этот метод? В этом действительно не должно быть ничего плохого…
3. вы правы, у меня возникла ошибка при инициализации объекта выше в иерархии и не освобождении его, что привело к утечке объекта на нижнем уровне.
Ответ №3:
Да, это произойдет, потому что в первой строке
self = [super init];
вы создаете один объект ( self
) и при self = array;
отменяете ссылку self
и переназначаете его. таким образом, более раннее значение находится в утечке.
Комментарии:
1. Спасибо, но можете ли вы явно сказать мне, что изменить в методе?
Ответ №4:
-(id)initWithNullCapacity:(int)capacity
{
self = [super init];
if (self) {
for (unsigned i = 0; i < capacity; i )
{
[self addObject:[NSNull null]];
}
}
return self;
}
должно выполнить задание
Комментарии:
1. Ну, когда я это делаю, компилятор выдает мне ошибку: -[NSMutableArray count]: метод, отправленный неинициализированному изменяемому объекту массива