【问题标题】:Is there any leak in NSAutoreleasepool?NSAutoreleasepool 中是否有任何泄漏?
【发布时间】:2015-07-28 12:14:13
【问题描述】:

会有什么结果?有没有泄漏或崩溃??

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

让我有点困惑。

【问题讨论】:

    标签: ios memory-leaks pool autorelease nsautoreleasepool


    【解决方案1】:
    1. 此代码违反内存管理规则。您执行alloc,因此您获得了+1 引用计数的所有权,然后您对其执行autorelease,这样您就放弃了您对引用计数的所有权。因此,您不应再使用name,并且不能保证指向有效对象。您返回它,一个指向可能无效对象的指针。
    2. 在这种特殊情况下,由于 Cocoa 的实现细节,不会发生任何“坏事”。该函数的主体相当于return @"Name";@"Name" 是一个字符串文字,字符串文字存储在静态存储中,在程序的整个生命周期中都存在。这意味着那些字符串对象不受内存管理——retainrelease 对它们无效。你对它执行[[NSString alloc] init...],但是NSString 的初始化器被优化为简单地保留并返回它的参数,如果参数已经是一个不可变的字符串。所以你没有返回一个新的NSString 对象;您只是返回静态分配且不受内存管理的相同字符串文字。同样,所有这些都是您不能依赖的 Cocoa 实现细节。

    【讨论】:

    • 所以在经历了你的解释之后,我对“字符串文字存储在程序的整个生命周期都存在的静态存储中”感到困惑,因为我认为它的生命在 { } 它声明的那个函数,除了使用 autorelease 关键字。你能给我解释一下吗?在非 ARC 中使用 xcode 6.1 打印名称?如果使用自动释放和同时排水池以及将释放消息发送到该对象,那么无效对象在哪里?请解释一下。
    • @Sandy:保留、释放、自动释放、分配、释放等都是关于对象的内存管理。该变量包含一个指向对象的指针。变量当然有作用域,但是指针变量的生命周期与对象的生命周期或内存管理无关。
    【解决方案2】:

    我提示上述内容可能会崩溃,因为[pool drain] 会导致 name 在返回之前被释放。

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

    池不是必需的,类似这样的尝试 -

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

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

    附带说明 - @autorelease { } 池块比 NSAutoreleasePool 更好用,甚至更好是切换到 ARC!

    【讨论】:

    • 在非 ARC 中使用 xcode 6.1 打印名称。在这里我很困惑,我的想法也一样。
    • 在这种情况下,不会发生崩溃,因为字符串文字是静态分配的,不受内存管理的影响,在不可变字符串上创建 NSString 只会返回该不可变字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 2010-11-25
    相关资源
    最近更新 更多