【发布时间】:2012-05-04 12:51:41
【问题描述】:
我有一个连接到附件的应用程序,当您断开附件时,我创建的用于与附件通信的 EASession 泄漏。
当配件连接时,我会收到通知并检查 EAAccessoryManager 的配件集合,以查找具有特定名称且使用特定协议的配件。当我找到这个时,我使用代码为该配件创建一个 EASession 对象:
-(void) openSession
{
... // finds accessory object
if (accessory)
{
[self closeSession];
session = [EASession alloc];
NSLog(@"alloc :: session retainCount: %i", session.retainCount);
[session initWithAccessory:accessory forProtocol:SmokeSignalsProtocolName];
NSLog(@"init :: session retainCount: %i", session.retainCount);
[[session inputStream] open];
[[session outputStream] open];
... // other logic (pump run loop, etc..)
}
}
-(void) closeSession
{
if (session)
{
[[session inputStream] close];
[[session outputStream] close];
[session release], session = nil;
}
}
通常我将 alloc 和 init 放在一行中,但我发现(像这样分开)alloc 提供 +1 保留计数(如您所料)但是 iniWithAccessory:forProtocol: 给它 +3 保留计数,而我只期望 init 方法中的 +2 保留计数。
泄漏工具似乎也支持这一点:
逐步查看泄漏仪器:
- +1 保留计数 ::
[???Accessory openSession]- 这是我分配新 EASession 的地方。 - +1 保留计数 ::
[EAInputStream iniWithAccessory:forSession:]输入流保存对拥有会话的引用。 - +1 保留计数 ::
[EAOutputStream initWithAccessory:forSession:]输出流保存对拥有会话的引用。 - +1 保留计数 ::
[EASession iniWithAccessory:forProtocol:]我不知道为什么这会增加 EASession 的保留计数。我相信这是造成我无法解释的额外保留计数的原因......不确定这应该如何平衡。这是 Apple 的错误吗?我需要给release打个电话来平衡一下……非常非常奇怪。 - -1 保留计数 ::
[EAInputStream close]清理上面的第 2 步 - -1 保留计数 ::
[EAOutputStream close]清理上面的第 3 步 - -1 保留计数 ::
???Accessory closeSession]清理上面的步骤 #11
那么...为什么我要泄漏 EASession 对象?使用 EASession 对象不泄漏的正确方法是什么?
编辑 - EADemo 不会泄漏,但...
EADemo 连接配件,但不漏电。出于好奇,我添加了一个额外的 [_session retain] 以使其泄漏,以便我可以在仪器中跟踪它的 malloc 历史。有趣的是,我的应用程序的 malloc 历史记录中没有调用一些内部调用。
你可以看到[EAAccessoryInternal removeSession:] 被调用了 3 次。这在我的应用程序的 malloc 历史中从未被调用过。我认为这是为什么我的 EASession 没有被释放的关键......
【问题讨论】:
-
关于拆分
alloc和init,您可能需要阅读此问题的答案:Why in Objective-C does doing alloc and init in separate statements cause the object to be released according to the Xcode static analyzer?。虽然可能不相关,但由于此处讨论的原因,不建议将这两者分开。 -
@BradLarson 感谢您的评论。我会将它们重新组合在一起并尝试一下。 EADemo 似乎可以正常工作而不会泄漏。在
alloc和initWithAccessory:forProtocol:之后它的保留计数也为4,但在释放EASession之前保留计数为1...所以我做错了什么。 -
我也看到了这个。如果您找到答案,请告诉我!
-
您是否尝试在流打开之前设置委托和 scheduleInRunLoop?
标签: ios memory-leaks external-accessory eaaccessory