Цель - C - NSMutableAttributedString Leak - PullRequest
       16

Цель - C - NSMutableAttributedString Leak

0 голосов
/ 11 августа 2011

Я новичок в Obj-C и экспериментирую с несколькими вещами. Я наткнулся на одну проблему утечки и хотел бы знать логическую причину этого.

Следующий фрагмент кода утечки :

(textViewAttrStr is an instance variable of type NSMutableAttributedString)

-(void) init:(NSString*)str
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str];
[textViewAttrStr appendAttributedString:part1String];
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"];
[textViewAttrStr appendAttributedString:part2String];
[textViewAttrStr retain];

[part1String release];
[part2String release];

[pool drain];
}

-(void) dealloc
{
if(textViewAttrStr != nil)
{
    [textViewAttrStr release];
}

[super dealloc];
}

пока следующий код не пропускает :

-(void) init:(NSString*)str
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str];
[tvas appendAttributedString:part1String];
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"];
[tvas appendAttributedString:part2String];

textViewAttrStr = tvas;
[textViewAttrStr retain];

[part1String release];
[part2String release];
[tvas release];

[pool drain];
}

-(void) dealloc
{
if(textViewAttrStr != nil)
{
    [textViewAttrStr release];
}

[super dealloc];
}

Может кто-нибудь объяснить, почему?

Ответы [ 3 ]

2 голосов
/ 11 августа 2011

Проблема с первым примером заключается в дополнительном удержании. Вы должны удалить это, потому что оно уже сохраняется при создании textViewAttrStr с [[NSMutableAttributedString alloc] initWithString:@"Hello "];

//Remove this line in the first example
[textViewAttrStr retain];
1 голос
/ 11 августа 2011

Первый пример:

textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 
//...
[textViewAttrStr retain];

Второй пример

NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "];
//...
[tvas release];

Теперь вы должны увидеть, что в своем первом примере вы выделили / init'd И сохранили его, к сожалению.

Во втором примере вы правильно распределили / init'd, а затем выпустили.

Простое правило: Если вы выделяете / init ИЛИ копируете ИЛИ сохраняете, ВЫ должны освободить в какой-то момент.Если это переменная класса, отпустите в dealloc, иначе отпустите перед выходом из области видимости.

0 голосов
/ 12 августа 2011

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

Во втором примере textViewAttrStr и tavs практически одинаковы. Они оба являются ссылками (или указателями) на один и тот же объект в памяти.

Итак, когда вы делаете:

textViewAttrStr = tvas;
[textViewAttrStr retain];
//...
[tvas release];

Призыв сохранить для этого объекта уравновешивается вызовом освобождения для этого объекта. Это в значительной степени ничего не делает. Удаление сохраняющих и освобождающих вызовов здесь обеспечивает ту же функциональность. После того, как вы удалите их, у вашего объекта счетчик ссылок 1, потому что вы вызвали alloc, а когда dealloc ударит, он достигнет 0 и будет освобожден.

Теперь, в вашем первом примере, ваш объект выделяется (счетчик ссылок 1), затем сохраняется (счетчик ссылок 2), и, когда Deloc ударит, он достигнет счетчика ссылок 1, а ваш объект не будет быть освобожден и, таким образом, утечка. Таким образом, решение здесь состоит в том, чтобы удалить вызов, чтобы сохранить.

Кстати, проверка того, что объекты не равны нулю, перед отправкой им сообщения о выпуске не нужна, потому что отправка сообщения на ноль ничего не делает.

...