Использование self.objectname заставляет профилировщик сообщать об утечке памяти - PullRequest
1 голос
/ 10 апреля 2011

Пожалуйста, помогите;

Заголовочный файл

#import <Foundation/Foundation.h>


@interface MyClass : NSObject {

    NSMutableString * myString;

}

@property (nonatomic, retain) NSMutableString * myString;

-(id) init;
-(void) dealloc;

@end

Файл реализации

#import "MyClass.h"


@implementation MyClass

@synthesize myString;

-(id) init {

    if ((self = [super init])) {
        self.myString = [[NSMutableString alloc] init];
    }

    return self;
}

-(void) dealloc {
    [super dealloc];
    [self.myString release];
}

@end

Использование

MyClass * m = [[MyClass alloc] init];
[m release];
//-- Xcode 4 profiler reports a memory leak here.

Однако, когда код вФайл реализации класса изменен, чтобы не использовать нотацию [self.myString .....], тогда утечка памяти не сообщается.

Итак,

    -(id) init {

           if ((self = [super init])) {
                myString = [[NSMutableString alloc] init];
            }

            return self;
        }
}

и

 -(void) dealloc {
        [super dealloc];
        [myString release];
    }

отлично работает.Об утечках памяти не сообщается.

Есть идеи - это профилировщик или я (будь любезен)?

Ответы [ 3 ]

2 голосов
/ 10 апреля 2011

Ваша утечка памяти не вызвана при использовании вашего сеттера.Утечка памяти вызвана тем, что вы неправильно управляете памятью!

Если вы объявите следующее свойство

@property (nonatomic, retain) id value;

Это означает, что компилятор генерирует методы, которые выглядят примерно так (очень упрощенно):

- (id)value {
  return value;
}

- (void)setValue:(id)aValue {
  [value autorelease];
  value = [aValue retain];
}

Когда вы используете точечную запись, self.value = obj выводится в [self setValue:obj].Отсюда вы фактически заставляете obj оставаться в сеттере.Если вы изначально создадите ссылку на obj (используя +alloc без соответствующего -release или -autorelease), у вас будет избыточное удержание obj, и оно никогда не будет освобождено.Следовательно, вам нужно сделать что-то вроде этого:

id obj = [[[NSObject alloc] init] autorelease];
self.value = obj;

или

id obj = [[NSObject alloc] init];
self.value = [obj autorelease];

или

id obj = [[NSObject alloc] init];
self.value = obj;
[obj release];

Что бы вы ни делали, вы должны убедиться, что когдаВы утверждаете право собственности на объект (сохраняя его), а также освобождаете его.

0 голосов
/ 10 апреля 2011

Методы установки в Objective-C приравнивают к воссоединению нового объекта и освобождению старого объекта.В вашем случае компилятор сгенерирует метод set для вашего свойства myString, который выглядит примерно так ...

- (void)setMyString:(NSMutableString*)aString {
    [myString autorelease];
    myString = [aString retain];
}

Когда вы вызываете self.myString = в вашем методе init, это переводится в вызов метода set.Сеттер, в свою очередь, сохраняет объект, который вы ему передаете.Поскольку вы непосредственно распределили строку NSString, в которой он начинает свою жизнь, с счетом сохранения, равным единице, вы затем вызываете установщик, и счет сохранения становится равным двум.добавить вызов к [autoStlease myString] после его выделения.Или, во-вторых, переключите ваш метод init, чтобы напрямую назначить ivar ...

// in your init method...
myString = [[NSMutableString alloc] init];

Хорошая идея - избегать использования сеттера в методах init, не из-за сохранения количества, а потому что объект в целом еще неполностью инициализирован.

0 голосов
/ 10 апреля 2011

@ property (nonatomic, RETAIN)

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

. Вот что вы должны сделать в методе INIT:

NSString *str = [[NSString alloc] initWithString:@"Hello World!"];
self.myString = str;
[str release]; // dont leak

Также я не рекомендую использовать self.somePropertyсам класс.Для этого требуется 1 дополнительный objc_msgSend () для доступа к вашей переменной и замедление работы вашего приложения.

...