【问题标题】:Is this the right way to use NSAutoreleasePool?这是使用 NSAutoreleasePool 的正确方法吗?
【发布时间】:2012-05-11 03:11:17
【问题描述】:

我是 Objective-C 的新手,我不确定我是否以正确的方式使用 NSAutoreleasePool。

  1. 如果我只想使用一次自动释放:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool release]; //newText will be released
    
  2. 如果我想多次使用 autorelease,我会使用:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool drain]; //newText will be released
    newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool drain]; //newText will be released
    newText = [NSString stringWithFormat:@"%d", prograssAsInt];
    sliderLabel.text = newText;
    [pool release]; //newText will be released
    

这样好吗?有没有内存泄漏?

【问题讨论】:

    标签: objective-c ios memory-management autorelease


    【解决方案1】:

    (2) 不行。 -drain-release 是等效的(在引用计数环境中),并且在 -draining 之后自动释放池被释放。因此,您将双重释放自动释放池对象并使程序崩溃。

    即使在 ARC 之前,除非您的内存预算非常紧张,否则在样板文件 main() 之外创建 NSAutoreleasePool 是非典型的。无论如何,每次 NSRunLoop 滴答后,池中的对象-autoreleased 都会被释放。如果严格遵守所有权转移规则(参见Understanding reference counting with Cocoa and Objective-C),就不会发生内存泄漏。

    并且 ARC 开启的情况下,您甚至不需要关心这一点——编译器会在适合您的位置插入-retain-release


    另外,如果sliderLabel.text 被标记为@property(retain)(或(strong)),那么在 (1) 中释放自动释放池将不会释放 newText,因为该对象现在有了新的所有者。

    【讨论】:

      【解决方案2】:

      我会说对[pool drain] 的调用是不必要的。我从未见过它们在实践中使用过。我想如果你在自动释放池中分配大量内存,这可能是必要的。但在典型情况下,我认为不会。

      顺便说一下,您将希望开始使用以下构造用于自动释放池:

      @autoreleasepool {
          ... your code ...
      }
      

      显然,这比“旧”方式(您正在使用的方式)更有效。从功能上讲,它是相同的,但在内部它的性能要好得多。最近的 Xcode/iOS 发行说明中对此有所了解。

      【讨论】:

        【解决方案3】:

        很抱歉这么说,但是RTFM。调用-drain后,池会自行释放,使其失效。

        而且,目前,在带有 Apple 的 LLVM 编译器的 Objective-c 中,有一个名为 @autoreleasepool 的语言添加,它适用于 ARC 和非 ARC 代码,您可以这样利用:

        @autoreleasepool {
            // code that will automatically have any -autoreleased variables cleaned up.
        } 
        

        【讨论】:

        • 我认为这种粗鲁是没有根据的。尽管这已记录在案,但它非常违反直觉,以至于我从经验丰富的 Cocoa 程序员那里听到,他们实际阅读了文档并且不相信它的意思是它所说的。对于刚接触框架的人来说,我认为这不是一个不合理的问题。
        【解决方案4】:

        通常,如果您在主线程上并且没有使用大量资源密集型代码循环,则您永远不需要创建自己的自动释放池。只需使用为您创建的默认设置即可。

        如果您使用多线程或正在执行内存密集型长时间运行循环(无论如何您可能不应该在主线程上执行),您只需要自己制作。

        【讨论】:

          猜你喜欢
          • 2018-12-31
          • 2021-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-05
          • 2017-02-01
          相关资源
          最近更新 更多