gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:53:18 25 4
gpt4 key购买 nike

我偶然发现了一个我在其他地方找不到答案的问题。当我调用一个返回指向一个对象的指针的方法时,该对象稍后被使用并在最后设置为 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com