代码之家  ›  专栏  ›  技术社区  ›  ahmet emrah

iPhone:这到底是不是一个漏洞

  •  5
  • ahmet emrah  · 技术社区  · 14 年前

    self.locationManager = [[CLLocationManager alloc] init];
    

    在Dealoc中:

       self.locationManager = nil;
    

    其中在.h文件中:

    @property (nonatomic, retain) CLLocationManager *locationManager;
    

    self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    

    然而,他声称这是行不通的,因为用他的话说:“不能自动释放类的属性。定义为保留的属性的自动生成访问器将自动处理保留”

    他让我怀疑是他错了还是我根本不懂内存管理?

    编辑1

    self.myName=[NSSting stringWithFormat:@"%@ is correct.", @"TechZen"];
    

    有什么不同于

     self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    

    内存管理明智吗?

    7 回复  |  直到 14 年前
        1
  •  7
  •   Colin Gislason    14 年前

    在这种情况下,计算保留和释放会有所帮助。这绝对是个漏洞。你的 locationManager 对象将保留2次:由 alloc/init nil 只会释放 位置经理

    对于编辑1中给出的示例,它们实际上是相同的。这听起来像是另一个开发人员对立即自动释放有反感,或者不太了解什么 autorelease

        2
  •  4
  •   VoidPointer    14 年前

    保持

    • 旧值(如果有)获取释放消息
    • 新值获取一条retain消息

    因此,在setter之后,CLLocationManager实例的retain计数将为2。一个来自 阿洛克 还有一个来自固定设置器。你应该发封信 释放

    CLLocationMamnager *aLocationManager = [[CLLocationManager alloc] init];
    self.locationManager = aLocationManager;
    [aLocationManager release];
    

    或者,将它添加到自动释放池中,这样它至少最终是免费的。就像你自己写的:

    self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    

    更好的是,不要使用 (默认设置)并且由于仍在使用保留对象,因此设置为“转到”。

        3
  •  2
  •   Andrew Johnson    14 年前

    以下声明保留两次,因此必须发布两次:

    self.locationManager = [[CLLocationManager alloc] init];
    

    self.locationManager = [[[CLLocationManager alloc] init]autorelease];
    

    现在,这个变量只保留了一次,您可以在类的dealloc函数中释放它。

    此外,如果运行以下代码行,则会调用一个版本:

    locationManager = nil;
    

    由于locationManager是合成的,所以当您将其设置为nil时,它首先被释放。

    self.locationManager = foo;
    

    self.locationManager = [[[CLLocationManager alloc] init]autorelease];
    [locationManager release];
    self.locationManager = foo;
    
        4
  •  1
  •   Russo    14 年前

    @你大错特错了。 所以,是的,提议的代码确实泄漏了,你必须像你想的那样发送自动释放消息,ahmet emrah

        5
  •  1
  •   Kendall Helmstetter Gelner    14 年前

        6
  •  0
  •   curv    14 年前

    NSLog(@"retainCount:%d", [locationManager retainCount]);
    

    [locationManager release];
    
        7
  •  -2
  •   TechZen    14 年前

    当您定义这样的属性时。。。

    @property (nonAtomic, retain) NSString myName;
    

    …由于property命令的默认值,它实际上类似于将其定义为:

    @property (nonAtomic, readwrite, retain, getter=getMyName,setter=setMyName) NSString myName;
    

    当你使用 @synthesize myName;

    -(void) setMyName:(NSString *) aString{
        if (!(myString==aString) { //test if a string is the same **object** as the current myString
            if (aString != nil) { // if nil we don't want to send a retain
                [aString retain]; // increment the retain count by one
            }        
            [myString release]; //decrement the retain count of the currently assigned string by one.
            myString=nil; //set the pointer to nil to ensure we don't point to the old string object
            myString=aString; //assign the newly retained object to the myString symbol     
        }
    }
    

    如您所见,任何来源的任何字符串,无论是否自动删除,都将在赋值时由该方法自动保留,并且当赋值时,该方法将自动释放该字符串。多个分配不会堆叠保留计数。只要使用生成的setter,分配的对象(在本例中为aString)将始终具有一个retain计数,这将使它在类中保持活动状态。

    这就是为什么你可以这样做。。。

    self.myName=[NSSting stringWithFormat:@"%@ is correct.", @"TechZen"]

    不必这样做:

    self.myName=[[NSSting stringWithFormat:@"%@ is correct.", @"TechZen"] retain];
    

    ... 当自动释放池耗尽时,不必担心字符串值是否会突然消失。

    [self.myName release]; 
    

    ... 世界以外的任何地方 dealloc ,则我的属性中的对象将为零,除非您无情地跟踪它。同样的道理,如果你打电话。。

    [self.myName retain];
    

    这就是为什么我说永远不要保留或自动释放在属性中指定或复制的任何对象。这不仅毫无意义,而且适得其反。因此,您只希望在处理完self对象后对属性调用release,因为setter对retain计数的有效跟踪意味着您可以将该属性置为零,即使您可能仍然需要该属性。

    一旦您了解了生成的访问器内部的情况,规则就显而易见了。永远不要显式保留属性的对象。永远不要释放属性的对象保存在dealloc中。永远不要自动释放属性的对象。

    这些规则的明显推论是始终在self对象内部使用self.propertyName引用,以确保自动管理属性的保留。