使用self.objectname会导致探查器报告内存泄漏

时间:2011-04-10 15:24:22

标签: objective-c memory-leaks

请帮助;

标头文件

#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 个答案:

答案 0 :(得分:2)

使用您的setter,造成内存泄漏 。您的内存泄漏是由于您没有正确管理内存造成的!

如果您声明以下属性

@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];

无论你做什么,你都需要确保当你断言对象的所有权时(保留它),你也要释放它。

答案 1 :(得分:0)

Objective-C中的Setter方法等同于重新获得新对象和释放旧对象。在您的情况下,编译器将为myString属性生成一个类似于...的

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

当你在init方法中调用self.myString =时,这会转换为对setter的调用。然后,setter会保留您传递给它的对象。因为你直接分配了NSString,它的保留计数为1,然后调用setter,保留计数变为2。

有两种解决问题的方法,第一种方法是在分配之后添加对[myString autorelease]的调用。或者其次切换你的init方法直接分配ivar ......

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

避免在init方法中使用setter是个好主意,不是因为保留计数,而是因为整个对象尚未完全初始化。

答案 2 :(得分:-3)

@property(非原子,RETAIN)

你保留了我的朋友。您必须释放该对象两次,因为保留计数为2

这是你应该在INIT方法中做的事情:

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

另外,我不建议在类本身中使用self.someProperty。这样做需要额外执行一次objc_msgSend()才能访问您的变量,并且会降低您的应用程序速度。