2015-07-28 78 views
2

会有什么结果?有没有泄漏或崩溃?NSAutoreleasepool中是否有泄漏?

-(NSString)returnPersonName { 
NSAutorelease *pool = [[NSAutorelease alloc]init]; 
NSString *name = [[[NSString alloc]initWithString:@"Name"]autorelease]; 
[pool drain]; 
return name 
} 

有点让我困惑。

回答

3
  1. 此代码违反了内存管理规则。你做alloc,所以你获得+1引用计数的所有权,然后你做它autorelease,通过它你放弃了你的引用计数的所有权。因此,您不应再使用name,并且不能保证指向有效的对象。您将其返回,指向潜在无效对象的指针。
  2. 在这种特殊情况下,由于Cocoa的实现细节,没有任何“坏”事情发生。该函数的主体相当于return @"Name";@"Name"是一个字符串文字,字符串文字存储在静态存储中,该静态存储在整个程序生命周期中都存在。这意味着这些字符串对象不受内存管理 - retainrelease对它们没有影响。您可以在其上执行[[NSString alloc] init...],但NSString的初始化程序已进行了优化,只需保留并返回它的参数(如果参数已经是不可变的字符串)。所以你没有返回一个新的NSString对象;你只是返回静态分配的,不受内存管理的字符串字面值。再次,所有这些都是你不能依赖的可可的实现细节。
+0

因此,经过你的解释后,我很困惑“字符串文字存储在静态存储器中存在的整个生命周期的程序”,因为我正在考虑作为局部变量,其生命是在{}函数中声明,除了使用autorelease关键字。你能向我解释一下吗?在非ARC中使用xcode 6.1时,其打印名称?哪里是无效对象如果使用autorelease和同一时间排水池以及将释放消息发送到该对象的权利?请解释。 – Sandy

+0

@Sandy:保留,释放,自动释放,分配,释放等都是关于对象的内存管理。该变量保存一个指向对象的指针。当然,变量有范围,但指针变量的生命周期与对象的生命周期或内存管理无关。 – newacct

2

我向小费上面可能会崩溃,因为[pool drain]将导致名称可以返回之前被释放。

在引用计数的环境中,drain方法的行为与release相同。由于无法保留自动释放池,因此会导致接收器被释放。当一个自动释放池被释放时,它向所有的自动释放对象发送释放消息。如果一个对象被多次添加到同一个池中,当池被释放时,它会在每次添加时收到一条释放消息。

池不是必需的,这样的事情尝试 -

-(NSString*)returnPersonName { 
    NSString *name = [[[NSString alloc]initWithString:@"Name"]autorelease]; 
    return name; 
    } 

更多信息可以在Advanced Memory Management Programming Guide

被发现在一个侧面说明 - 一个@autorelease { }池块是更好地使用比NSAutoreleasePool更好切换到ARC!

+0

使用xcode 6.1在非ARC中打印其名称。在这里我很困惑,我也在想。 – Sandy

+0

在这种情况下,不会发生崩溃,因为字符串文字是静态分配的,不受内存管理的影响,并且在不可变字符串上创建'NSString'只会返回该不可变字符串。 – newacct