6

我有一个连接到附件的应用程序,当您断开附件时,我创建的用于与附件通信的 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 retainCount。

泄漏工具似乎也支持这一点:

在此处输入图像描述

一步一步看泄漏仪器:

  1. +1 保留计数 :: [???Accessory openSession]- 这是我分配新 EASession 的地方。
  2. +1 保留计数 ::[EAInputStream iniWithAccessory:forSession:]输入流保留对拥有会话的引用。
  3. +1 保留计数 ::[EAOutputStream initWithAccessory:forSession:]输出流保留对拥有会话的引用。
  4. +1 保留计数 ::[EASession iniWithAccessory:forProtocol:] 我不知道为什么这会增加 EASession 的保留计数。我相信这是造成我无法解释的额外保留计数的原因......不确定这应该如何平衡。这是Apple的错误吗?我需要release额外的时间来平衡事情……非常非常奇怪。
  5. -1 保留计数 ::[EAInputStream close] 清理上面的步骤 #2
  6. -1 保留计数 ::[EAOutputStream close] 清理上面的第 3 步
  7. -1 保留计数 ::???Accessory closeSession]清理上面的步骤 #11

那么...为什么我要泄漏 EASession 对象?使用 EASession 对象不泄漏的正确方法是什么?


编辑 - EADemo 不会泄漏,但...

EADemo连接到配件,但不会泄漏。出于好奇,我添加了一个额外[_session retain]的内容以使其泄漏,以便我可以在仪器中跟踪它的 malloc 历史。有趣的是,我的应用程序的 malloc 历史记录中没有调用一些内部调用。

在此处输入图像描述

你可以看到这已经[EAAccessoryInternal removeSession:]调用了 3 次。这在我的应用程序的 malloc 历史中从未被调用过。我认为这是为什么我的 EASession 没有被释放的关键......

4

2 回答 2

1

虽然演示以相反的方式进行,但我设法通过在将输入和输出关闭方法从运行循环中删除并将它们的委托设置为 nil后调用来修复此泄漏。

于 2014-04-14T09:58:03.627 回答
1

我知道这个讨论现在已经很老了,但我最近使用 ARC 等时遇到了完全相同的问题,我发现解决它的一种方法是不关闭输入或输出流。只需有一个处理所有输入等的类,并根据请求将数据转发到应用程序的其他部分。您可以重新分配初始化 EASession 对象,而不会收到 XCode 的投诉,因此我假设旧的 EASession 已被释放,因为我的 APP 不再引用它。但是,我还没有检查泄漏。

于 2014-03-16T12:18:31.957 回答