我使用 ARC 构建了一个简单的琐事游戏。在 Xcode 中使用 Allocations 分析工具分析其内存使用情况时,我发现内存并不总是被释放。对于问题的一个示例,我有一个 ActivePlayer 对象的类:
活动播放器.h:
@interface ActivePlayer : NSObject
@property (nonatomic, strong) NSString * name;
@property (nonatomic) NSInteger overallScore;
@property (nonatomic) NSInteger questionScore;
- (id) initWithName:(NSString *)name;
@end
活动播放器.m:
#import "ActivePlayer.h"
@interface ActivePlayer ()
@end
@implementation ActivePlayer
- (id) initWithName:(NSString *)name
{
self = [self init];
if (self) {
self.name = name;
self.overallScore = 0;
}
return self;
}
/*
- (void)dealloc
{
self.name = nil;
}
*/
@end
ActivePlayer 是在 ActiveGame 类的 createPlayer 方法中创建的:
[[ActivePlayer alloc] initWithName:name]
我正在执行以下测试用例:我开始一个新游戏(分配一个 ActivePlayer),我回答一个问题,然后游戏结束(此时 ActivePlayer 被释放)。然后我可以开始另一个游戏并重复这个循环(每个循环都是一个“游戏”,如下所述)。在使用 Allocations 分析工具时,我期望看到的是内存已在游戏中间分配,但在游戏结束后已被释放(无论我玩游戏多少次)。但我发现情况并非总是如此:
顺便说一句:下面的每个项目符号行描述了分配工具的对象列表选项卡中的一行;该站点不允许我发布屏幕截图,因此是文字说明。所有行都是实时的;我只查看 Created 和 Still Living 分配。
当游戏 #1 正在进行时,我看到了以下分配。
- 类别=ActivePlayer;尺寸=16;负责任的调用者=-[ActiveGame createPlayer:]
- 类别=Malloc 48 字节;大小=48;负责任的调用者=-[ActivePlayer initWithName:]
游戏 #1 完成后,我看到以下内容。ActivePlayer 对象已被释放,但 48 字节仍然是 Live 的。
- 类别=Malloc 48 字节;大小=48;负责任的调用者=-[ActivePlayer initWithName:]
如果我开始游戏 #2,我会在游戏进行时看到以下内容。除了游戏 #1 中的分配之外,还有两种新分配。
- 类别=Malloc 48 字节;大小=48;负责任的调用者=-[ActivePlayer initWithName:]
- 类别=ActivePlayer;尺寸=16;负责任的调用者=-[ActiveGame createPlayer:]
- 类别=Malloc 144 字节;大小=144;负责任的调用者=-[ActivePlayer initWithName:]
在游戏 #2 完成后,我看到以下内容。同样,ActivePlayer 对象已被释放,但“Malloc X Bytes”分配仍然存在。
- 类别=Malloc 48 字节;大小=48;负责任的调用者=-[ActivePlayer initWithName:]
- 类别=Malloc 144 字节;大小=144;负责任的调用者=-[ActivePlayer initWithName:]
在那之后,我得到了不寻常的结果——如果我玩游戏 #3、#4 和 #5,我再也看不到 Category="Malloc X Bytes" 的游戏行,只有 Category=ActivePlayer 的新行,即游戏结束后释放。如上所示,前两个“Malloc”行继续存在。我还看到了其他奇怪的行为——昨天在使用 iPhone 6.0 模拟器进行测试时,只有在游戏 #2 和 #3 之后才留下实时内存,而不是游戏 #1、#4 和 #5。因此,虽然内存仍然分配,但它发生的时间似乎因我的设备和不同版本的模拟器而异。
还有我的问题:
- 我的理解是否正确,在游戏结束并且 ActivePlayer 对象已被释放后,我不应该从调用 initWithPlayer 中看到任何实时内存?
- 如果是,是什么原因造成的,我该如何解除分配?
- 还是我根本不需要担心?
笔记:
- 这些屏幕截图来自在运行 iOS 6.1 的 iPhone 4 上运行我的应用程序。但是我在 5.1、6.0 和 6.1 的 iPhone 模拟器上看到了类似的行为,而且我在升级之前在运行 iOS 6.0 的 iPhone 上看到了它。
- 在 ActivePlayer.m 中,dealloc 方法目前已被注释掉,尽管我已经在它未被注释的情况下进行了测试,并验证了它正在被调用(由系统调用;我不直接在任何地方调用 dealloc)。无论哪种方式,行为都是相同的。
- 对于它的价值,Leaks 分析工具没有报告任何内容。
- 虽然这是一个导致我认为应该释放 192 字节的活动内存的示例,但我在我的许多课程中都看到了这一点,即内存分配似乎随着时间的推移而增长,我认为这是一个问题。