EASession Leaks

Sam*_*Sam 6 memory-leaks external-accessory ios eaaccessory

我有一个连接到附件的应用程序,当我断开附件时,我创建的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

通常我在一行上有alloc和init,但我发现(将其分离出来)是alloc给出了+1保留计数(正如你所期望的那样)但是iniWithAccessory:forProtocol:给它+3保留计数当我只会期望来自init方法的+2 retainCount.

泄漏仪器似乎也支持这一点:

在此输入图像描述

一步一步看看泄漏仪器:

  1. +1保留计数:: [???Accessory openSession]- 这是我分配新EASession的地方.
  2. +1 retain count :: [EAInputStream iniWithAccessory:forSession:]输入流将引用保存回拥有的会话.
  3. +1 retain count :: [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]清除步骤#1以上1

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


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

EADemo连接到配件,但它不会泄漏.出于好奇,我添加了一个额外的东西[_session retain]以使其泄漏,所以我可以在乐器中遵循它的malloc历史.看到我的应用程序的malloc历史记录中没有调用一些内部事件,这很有趣.

在此输入图像描述

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

小智 1

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