用“ self.variable = value”两次设置实例变量会导致内存泄漏?

| 直到昨天,我还以为我已经了解了iPhone的内存管理。 好吧,这是我的问题:
// .h file
     @property(nonatomic, retain) NSMutableDictionary *dicParams;
     @property(nonatomic, retain) NSMutableDictionary *dicReferences;
     @property(nonatomic, retain) FtMonitorHandler *monitorHandler;

// .m file
@synthesize dicParams, dicReferences, monitorHandler;

- (id)init {
    self = [super init];

    if (self) {
        self.dicParams = [[NSMutableDictionary alloc] init];
        self.dicReferences = [[NSMutableDictionary alloc] init];
        self.monitorHandler = [[FtMonitorHandlerService alloc] init];
    }
    return self;
}


- (void)dealloc {
    [monitorHandler release];
    [dicParams release];
    [dicReferences release];
    [super dealloc];
}
如果我在其他地方设置,例如在分配视图控制器之后
self.dicParams = dicValues;
…会变成泄漏 我对使用\“ self。…\”设置实例变量的理解是,当前值将为\“ released \”,然后使用\“ retain \”进行设置。 我尝试了一些乐器。结果:
-(void)createLeak { 
    self.dicParams = [[NSMutableDictionary alloc] init]; 
    self.dicParams = [[NSMutableDictionary alloc] init]; 
}

-(void)createAnotherLeak { 
    self.dicParams = [[NSMutableDictionary alloc] init]; 
    self.dicParams = nil; 
    self.dicParams = [[NSMutableDictionary alloc] init]; 
}

- (void)createWithoutLeak { 
    if(dicParams != nil) [dicParams release]; 
    self.dicParams = [[NSMutableDictionary alloc] init];
}
我是否错过了某些事情,或者这是应有的行为? 编辑:我试图实施建议的更改。只要我的变量不是GUI元素,它就可以正常工作。 (UIView,UILabel等) 内存警告后,自动释放会导致应用程序崩溃
- (void)loadView {  
    [super loadView];
    // ... here is some other stuff ...  
    self.lblDeparture = [[[UILabel alloc] init] autorelease];  
}  

- (void)viewDidUnload {  
    [super viewDidUnload];  
    // Release any retained subviews of the main view.  
    self.lblDeparture = nil;
}

- (void)dealloc {  
    [lblDeparture release];  
    [super dealloc];  
}  
我不太确定,但我认为以下几行是真正的问题:
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, INFO_VIEW_HEIGHT);  
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];  

[imageView addSubview:lblDeparture];  
[lblDeparture release];  // is this correct?

[self.view addSubview:imageView];  
[imageView release];  
    
已邀请:
如果您进行初始化,则需要自动释放。
-(void)dontCreateAnotherLeak {
    self.dicParams = [[[NSMutableDictionary alloc] init] autorelease];
    self.dicParams = nil;
    self.dicParams = [[[NSMutableDictionary alloc] init] autorelease];
}
等效的方法是使用便捷访问器。
self.dicParams = [NSMutableDictionary dictionary];
如果您想自己解决这个问题。在@synthesize dictParams之上;您还需要创建自己的二传手。
-(void)setDictParams:(NSMutableDictionary*) newDictParams
{
    if (dictParams != newDictParams)
    {
        [dictParams release];
        dictParams = [newDictParams retain];
    }
}
这有点简单。但本质上是编译器在将保留修饰符添加到@property标记后创建的内容     
如果设置了在which9ѭ中指定了
retain
的实例变量,则保留计数变为1 现在,当您引用self时,例如“ self.variable = value”,将case8ѭ计数增加1,因此总保留计数变为2。 因此,现在要释放它,您需要将保留计数设为0。因此,您需要释放两次。 Hopew这会有所帮助。     
我不确定我是否完全理解这个问题,但是您的第二部分很容易解释...   -(void)createLeak {
self.dicParams = [[NSMutableDictionary alloc] init];

self.dicParams = [[NSMutableDictionary alloc] init];
很明显... 现在但是这个   -(void)createAnotherLeak {
self.dicParams = [[NSMutableDictionary alloc] init];

self.dicParams = nil;

self.dicParams = [[NSMutableDictionary alloc] init]; }
不会释放第一个已分配的self.dicParams,而是通过将其设置为nil,然后用一个新值将其重置来忘记对它的任何引用。设置为nil不等于释放。如果您要使用自动发布功能创建第一个,然后将其设置为nil,那就有些不同了。那应该正常工作。这就是您对第三个示例所做的出色表现! 现在关于您的初始问题,当您撰写时泄漏了什么?   self.dicParams = dicValues; ? 变量self.dicParams应该只保存该值,直到再次释放它为止     
我建议您仔细阅读Apple的《内存管理编程指南》。 http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html 在那里都有所有解释。 我可以看到您正在犯几个明显的错误。 首先,您不应该在
init
dealloc
中使用访问器。 所以这
- (id)init { 
 self = [super init];

 if (self) {
    self.dicParams = [[NSMutableDictionary alloc] init];
    self.dicReferences = [[NSMutableDictionary alloc] init];
    self.monitorHandler = [[FtMonitorHandlerService alloc] init];
 }
 return self;
} 
应该
- (id)init { 
 self = [super init];

 if (self) {
    dicParams = [[NSMutableDictionary alloc] init];
    dicReferences = [[NSMutableDictionary alloc] init];
    monitorHandler = [[FtMonitorHandlerService alloc] init];
 }
 return self;
} 
其次,当您设置保留属性时,您需要释放其设置的内容。 所以这
self.dicParams = [[NSMutableDictionary alloc] init];
应该
self.dicParams = [[[NSMutableDictionary alloc] init] autorelease];
或者你可以这样做
NSMutableDictionary *newDicParams = [[NSMutableDictionary alloc] init];
self.dicParams = newDicParams;
[newDictParams release];
    
@synthesize
(readwrite, retain, nonatomic)
属性生成的设置器如下所示:
 - (void) setSomething: (id) newSomething;
 {
      if (something != newSomething) {
          [something release];
          something = [newSomething retain];
      }
 }
由实例变量“ 23”指向的旧对象将被释放,而新对象将被保留。 您的错误是对象创建。您用
[[NSDictionary alloc] init]
创建字典。该词典的保留计数为1。您的setter保留了该对象,因此新的保留计数为2。当您再次调用setter时,原始词典的保留计数将正确减少-再次为1。要释放字典,您必须再次释放它。为此,有25英镑。自动释放的对象将在一段时间后释放。所以设置属性的正确代码是
 self.something = [[[NSDictionary alloc] init] autorelease];
甚至更好的使用便利分配器
 self.something = [NSDictionary dictionary];
您确实应该阅读并理解Apple的内存管理指南-在那里进行了全部解释。 顺便说一句,我在这里谈到保留数。可以考虑它们,但是您永远不要问一个对象有关其保留计数的问题,该值是无用的,因为它很少能想到。     

要回复问题请先登录注册