我有一个连接到附件的应用程序,当断开附件时,我创建的用于与附件通信的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放在一行上,但是我发现(这样分离出来)的是,分配给+1保留计数(如您所愿)但是 iniWithAccessory:forProtocol:给它+3保留当我只希望init方法获得+2 keepCount时计数。

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

逐步查看泄漏仪器:
  • +1保留计数:: [???Accessory openSession]-这是我分配新的EASession的地方。
  • +1保留计数:: [EAInputStream iniWithAccessory:forSession:]输入流保留对拥有会话的引用。
  • +1保留计数:: [EAOutputStream initWithAccessory:forSession:]输出流保留对拥有会话的引用。
  • +1保留计数:: [EASession iniWithAccessory:forProtocol:]我不知道为什么这会增加EASession的保留计数。我认为这是造成我无法解释的额外保留人数的原因...不知道应该如何平衡。这是苹果的bug吗,我需要额外打电话给release来平衡事物...。非常奇怪。
  • -1保留计数:: [EAInputStream close]清理
  • 上方的第2步
  • -1保留计数:: [EAOutputStream close]清理
  • 上方的第3步
  • -1保留计数:: ???Accessory closeSession]清理上面的步骤#1

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

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

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

    您可以看到[EAAccessoryInternal removeSession:]被调用了3次。在我的应用程序的malloc历史记录中从未调用过此方法。我认为这是为什么不发布我的EASession的关键...

    最佳答案

    我知道现在的讨论已经很久了,但是最近使用ARC e.t.c遇到了同样的问题。我发现解决它的一种方法是不关闭输入或输出流。只需拥有一个可处理所有输入e.t.c的类,然后根据请求将数据转发到应用程序的其他部分。您可以重新分配EASession对象,而不会受到XCode的抱怨,所以我认为旧的EASession已被释放,因为我的APP不再引用它。
    我还没有检查泄漏。

    07-24 12:27