未使用ARC在iOS应用程序中释放内存
我用ARC构建了一个简单的琐事游戏。在使用Xcode中的分配分析工具分析其内存使用情况时,我发现内存并不总是被释放的。例如,我有一个ActivePlayer对象的类: ActivePlayer.h:未使用ARC在iOS应用程序中释放内存,ios,memory-management,automatic-ref-counting,Ios,Memory Management,Automatic Ref Counting,我用ARC构建了一个简单的琐事游戏。在使用Xcode中的分配分析工具分析其内存使用情况时,我发现内存并不总是被释放的。例如,我有一个ActivePlayer对象的类: ActivePlayer.h: @interface ActivePlayer : NSObject @property (nonatomic, strong) NSString * name; @property (nonatomic) NSInteger overallScore; @property (nonatomic)
@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是在ActiveGame类中的createPlayer方法中创建的:
[[ActivePlayer alloc] initWithName:name]
我正在执行以下测试用例:我开始一个新游戏(分配一个ActivePlayer),回答一个问题,然后游戏结束(此时ActivePlayer被解除分配)。然后我可以开始另一个游戏并重复这个循环(每个循环都是一个“游戏”,如下所述)。在使用分配分析工具时,我希望看到的是内存已经分配在游戏中间,但在游戏结束后被释放(不管我玩了多少次游戏)。但我发现情况并非总是如此:
顺便说一句:下面的每个项目符号行描述了“分配”工具的“对象列表”选项卡中的一行;这个网站不允许我发布截图,因此有文字描述。所有行都是活动的;我只查看创建的和仍然存在的分配
在游戏1进行期间,我看到了以下分配
- 类别=活动玩家;尺寸=16;负责呼叫方=-[ActiveGame createPlayer:]
- 类别=Malloc 48字节;尺寸=48;负责调用方=-[ActivePlayer initWithName:]
- 类别=Malloc 48字节;尺寸=48;负责调用方=-[ActivePlayer initWithName:]
- 类别=Malloc 48字节;尺寸=48;负责调用方=-[ActivePlayer initWithName:]
- 类别=活动玩家;尺寸=16;负责呼叫方=-[ActiveGame createPlayer:]
- 类别=Malloc 144字节;尺寸=144;负责调用方=-[ActivePlayer initWithName:]
- 类别=Malloc 48字节;尺寸=48;负责调用方=-[ActivePlayer initWithName:]
- 类别=Malloc 144字节;尺寸=144;负责调用方=-[ActivePlayer initWithName:]
- 我的理解正确吗?在游戏结束并且ActivePlayer对象被释放后,我不应该从调用initWithPlayer中看到任何活动内存李>
- 如果是,原因是什么,如何解除分配
- 或者我根本不需要担心它
- 这些截图来自在运行iOS 6.1的iPhone 4上运行我的应用程序。但我在5.1、6.0和6.1版的iPhone模拟器上看到了类似的行为,在升级之前,我在运行iOS 6.0的iPhone上看到了类似的行为
- 在ActivePlayer.m中,dealloc方法目前已被注释掉,尽管我已经在未注释的情况下进行了测试,并验证了它正在被调用(由系统调用;我不会在任何地方直接调用dealloc)。不管怎样,行为都是一样的
- 值得一提的是,泄漏分析工具没有报告任何内容
- 虽然这是一个我认为应该释放192字节活动内存的例子,但我在我的许多类中都看到了这一点,即内存分配似乎随着时间的推移而增加,我认为这是一个问题李>
[[ActivePlayer alloc] initWithName:@"Bob"];
您的init方法应该使用
[super init];
我觉得很奇怪,你的构造函数是静态的(+符号)。命名约定要求名称前缀为
init
的方法返回托管内存对象。我怀疑内部方法的结果是根据它们的方法名进行评估的 我认为实例计数测试确定您的代码没有泄漏ActivePlayer。另一方面,构造函数和初始化的更好形式如下:
// .h
@interface ActivePlayer : NSObject
+ (id)activePlayerWithName:(NSString *)name;
@end
// .m
+ (id)activePlayerWithName:(NSString *)name {
return [[self alloc] initWithName:name];
}
// if you want to make this public (include in .h interface) you can
// the callers will have the choice of alloc init pattern, or the factory
//
- (id)initWithName:(NSString *)name {
self = [self init];
if (self) {
_name = name;
}
return self;
}
然后调用方执行以下操作:
ActivePlayer *activePlayer = [ActivePlayer activePlayerWithName:@"Charlie"];
问题可能出现在代码的其他地方。你能多发一些吗?某些时候,某些东西一定保存着对ActivePlayer对象的引用。你能看到在哪里,通过哪些对象,retain计数增加了吗?我也想到了这一点,并寻找了ActivePlayer对象可能被引用的其他地方。但是,如果是其他对象持有对ActivePlayer的引用,那么我希望行“Category=ActivePlayer;Size=16;Responsible Caller=+[ActivePlayer initWithName:]”仍然存在于对象列表中(它不存在),并且(2)不会调用对象的dealloc方法(我已经验证了它正在被调用)。再次,如果我的理解是正确的……让我们使用dealloc来实现调试优势:在fi中创建一个静态int