我使用ARC构建了一个简单的琐事游戏。在使用Xcode中的Allocations概要分析工具分析其内存使用情况时,我发现内存并不总是被释放。对于这个问题的一个例子,我有一个类用于ActivePlayer对象:使用ARC的iOS应用程序未释放内存
ActivePlayer.h:
@interface ActivePlayer : NSObject
@property (nonatomic, strong) NSString * name;
@property (nonatomic) NSInteger overallScore;
@property (nonatomic) NSInteger questionScore;
- (id) initWithName:(NSString *)name;
@end
ActivePlayer.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以创建的createPlayer方法在一个ActiveGame类:
[[ActivePlayer alloc] initWithName:name]
我正在执行以下测试用例:我明星一个新游戏(分配一个ActivePlayer),我回答一个问题,然后游戏结束(此时ActivePlayer被释放)。然后我可以开始另一场比赛并重复这个循环(每个循环都是“游戏”,如下所述)。在使用Allocations分析工具时,我期望看到的是内存在游戏中间分配,但在游戏结束后(无论我玩游戏的次数多少),已经释放内存。但我发现这并非总是如此:
顺便说一句:下面的每个项目符号行描述了分配工具的Objects List选项卡中的一行;本网站不会让我发布截图,因此文字说明。所有行都是实时的;我只查看创建和静态分配。
第1场比赛正在进行中,我看到下列分配。
- 类别= ActivePlayer;大小= 16; Responsible Caller = - [ActiveGame createPlayer:]
- Category = Malloc 48 Bytes;大小= 48; Responsible Caller = - [ActivePlayer initWithName:]
游戏#1完成后,我看到以下内容。 ActivePlayer对象已被释放,但48个字节仍为Live。
- 类别= Malloc 48 Bytes;大小= 48; Responsible Caller = - [ActivePlayer initWithName:]
如果我开始游戏#2,在游戏进行时我会看到以下内容。除了第一场比赛之外,还有两个新的分配。
- 类别= Malloc 48 Bytes;大小= 48; Responsible Caller = - [ActivePlayer initWithName:]
- Category = ActivePlayer;大小= 16;负责任的来电= - [ActiveGame createPlayer:]
- Category = Malloc 144 Bytes;大小= 144;负责任的来电者= [ActivePlayer initWithName:]
并且在游戏#2完成后,我看到以下内容。同样,ActivePlayer对象已被释放,但“Malloc X Bytes”分配仍然存在。
- 类别= Malloc 48 Bytes;大小= 48; Responsible Caller = - [ActivePlayer initWithName:]
- Category = Malloc 144 Bytes;大小= 144;负责来电= - [ActivePlayer initWithName:]
在那之后,我得到的不寻常的结果 - 如果我玩游戏#3,#4,#5,我从来没有看到在游戏中的行为类别=“的malloc X字节“,只有Category = ActivePlayer的新行,在游戏结束后释放。如上所示,前两个“Malloc”行继续存在。我还看到了其他奇怪的行为 - 在使用iPhone 6.0模拟器进行测试时,仅在游戏#2和#3之后,而没有游戏#1,#4和#5时,活动内存才被留下。所以,尽管内存仍然是分配的,但它发生的时间似乎在我的设备和不同版本的模拟器上有所不同。
而且我的问题:
- 我的理解是正确的,我不应该看到从游戏结束,ActivePlayer对象后调用initWithPlayer任何实时内存被释放?
- 如果是,导致它的原因是什么,以及如何取消分配?
- 或者我不需要担心它吗?
注:
- 这些截图来自于运行iOS 6.1的iPhone 4上运行我的应用程序。但是我看到类似的行为与iPhone Simulator for 5.1,6.0和6.1一起运行,我在升级之前在运行iOS 6.0的iPhone上看到它。
- 在ActivePlayer.m中,dealloc方法当前已被注释掉,尽管我已经在未被注释的情况下进行了测试,并且已经验证了它被调用(由系统;我不直接在任何地方调用dealloc)。无论哪种方式,行为都是一样的。
- 值得一提的是,Leaks剖析工具并未报告任何内容。
- 虽然这是一个导致192字节的活内存的例子,我相信应该释放,但我看到这与我的许多类,即看起来内存分配随着时间增长,我认为是一个问题。
*这个问题可能在其他地方在你的代码*你能发布更多?有些时候必须持有对ActivePlayer对象的引用。你能看到保留计数增加的位置和哪个对象? – paulmelnikow 2013-02-12 23:58:40
我想到了这一点,并寻找可能引用ActivePlayer对象的其他地方。但是,如果某些其他对象持有对ActivePlayer的引用,那么我会预期“Category = ActivePlayer; Size = 16; Responsible Caller = + [ActivePlayer initWithName:]”行仍然会存在于对象列表(它不)和(2)对象的dealloc方法不会被调用(我已经验证它被调用)。再次,如果我的理解是正确的... – 2013-02-13 00:09:46
让我们使用该dealloc来获得调试优势:在文件中创建一个静态int并将其增加到您的alloc init行旁边。记录在那里。然后递减并记录到dealloc中。 – danh 2013-02-13 00:34:30