ios - ARC 并释放在方法中创建的对象

标签 ios objective-c memory-management automatic-ref-counting

我偶然发现了一个我在其他地方找不到答案的问题。当我调用一个返回指向一个对象的指针的方法时,该对象稍后被使用并在最后设置为 nil,它仍然分配在内存中(根据 Instruments)。我正在使用 XCode 4.6.3 和 iOS 6.1。 ARC 已打开。

示例代码如下:

A类.h

@interface ClassA : NSObject
    -(void)runSomething;
@end

A类.m

#import "ClassA.h"
#import "ClassB.h"

@implementation ClassA

-(void)runSomething {
    int counter = 0;
    while (true) {
        ClassB *instance = [self makeClassBWithNumber:counter];
        NSLog(@"%d", [instance getNumber]);
        [NSThread sleepForTimeInterval:0.01];
        instance = nil;
        counter++;
    }
}

-(ClassB*) makeClassBWithNumber:(int)number {
    return [[ClassB alloc] initWithNumber:number];
}

@end

B类.h

@interface ClassB : NSObject
@property int number;
    -(id)initWithNumber:(int)number;
    -(int)getNumber;
@end

B类.m

#import "ClassB.h"

@implementation ClassB

-(id)initWithNumber:(int)number {
    self = [super init];
    if(self) {
        _number = number;
    }
    return self;
}

-(int)getNumber {
    return [self number];
}

@end

ClassB 在 View Controller 中创建并调用方法 runSomething。此示例代码生成创建的对象 (ClassB) 永远不会从内存中释放。如果我从

更改代码

ClassB *instance = [self makeClassBWithNumber:counter];

ClassB *instance = [[ClassB alloc] initWithNumber:counter];

创建的对象在每个循环周期中被正确释放。这种行为的原因是什么?我在 stackoverflow 上找到了一些旧答案,makeClassBWithNumber 应该返回结果调用 autorelease return [result autorelease],但如果启用了 ARC,则无法完成。

最佳答案

不同之处在于 +alloc 返回一个带有 +1 保留的对象,ARC 将在其范围结束时与释放进行平衡,因此立即释放。 +make ... 返回一个带有 +1 保留和匹配自动释放的对象。自动释放池将在耗尽时发送一条 release 消息。由于您在“为真时”处于循环中,因此自动释放池永远不会耗尽并且您会积累内存。

解决方案是给你的循环一个自动释放池:

while (true) {
    @autoreleasepool { // <== Add an autorelease block here.
      ClassB *instance = [self makeClassBWithNumber:counter];
      //NSLog(@"%d", [instance getNumber]);
      NSLog(@"%d", [instance number]); // Fix naming; do not prefix accessors with `get`
      [NSThread sleepForTimeInterval:0.01];
      // instance = nil; // Does nothing in this loop.
      counter++;
    }
}

这将导致池在每次迭代时耗尽。在任何情况下,instance=nil 都是不必要的。


编辑:一定要阅读 MartinR 的回答。它提供了有关实现细节的更多详细信息,特别是为什么这可能会因优化级别而有所不同,以及被调用方法是否与调用方法位于同一编译单元(.m 文件)中。那只是一个优化细节;您仍然需要将此 @autoreleasepool 放入循环中以确保正确性。

关于ios - ARC 并释放在方法中创建的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18727445/

相关文章:

iOS8/模拟器 - SFHFKeychainUtils 错误,SFHFKeychainUtilsErrorDomain 错误 -34018

ios - 是否可以访问 iOS 系统动画的属性?

objective-c - -self parentViewController- dismissModalViewController 不适用于 iOS 5

ios - 如何通过 iOS 版 Facebook 应用程序使用 Facebook 登录

ios - 按顺序动画 View 和 subview

ios - 在 ios8 xcode6 中找不到 <coreaudiokit/coreaudiokit.h>

ios - SecAddItem 只返回 errSecParam,不管我做什么

memory-management - 数组如何存储在内存中?

java - Android 堆转储转换为 J2SE : hprof-conv: command not found

java - 为什么 Java System.gc() 没有按预期工作?