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 を 1 行に持っていますが、(このように分離して) 見つけたのは、alloc が +1 の保持カウントを与えることです (ご想像のとおり) iniWithAccessory:forProtocol:。 init メソッドからの +2 の保持カウントのみを期待します。

リークインストゥルメントもこれをサポートしているようです。

ここに画像の説明を入力

リーク計測器を段階的に見ていきます。

  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]上記のステップ #1 をクリーンアップします1

だから...なぜ私はEASessionオブジェクトを漏らしているのですか? リークしないために EASession オブジェクトを使用する適切な方法は何ですか?


編集 - EADemo はリークしませんが ...

EADemoはアクセサリーに接続しますが漏れません。好奇心から[_session retain]、インストゥルメントで malloc の履歴をたどることができるように、リークを発生させるエクストラを追加しました。私のアプリの malloc 履歴で呼び出されなかったいくつかの内部的なものを見るのは興味深いことでした。

ここに画像の説明を入力

[EAAccessoryInternal removeSession:]これが3 回呼び出されたことがわかります。これは、アプリの malloc 履歴で呼び出されたことはありません。これが、私の EASession がリリースされない理由の鍵だと思います...

4

2 に答える 2

1

デモでは逆に行っていますが、実行ループから削除してデリゲートを nil に設定した、入力と出力の close メソッドを呼び出すことで、このリークを修正することができました。

于 2014-04-14T09:58:03.627 に答える
1

この議論は今ではかなり古いことを知っていますが、最近ARCなどを使用してまったく同じ問題を抱えていました.1つの方法は、入力ストリームまたは出力ストリームを閉じないことです. すべての入力などを処理し、リクエストに応じてデータをアプリケーションの他の部分に転送するクラスを作成するだけです。XCode からの苦情なしで EASession オブジェクトを再割り当てできるので、古い EASession は私の APP によって参照されなくなったため、問題なく解放されていると想定しています。ただし、漏れはまだ確認していません。

于 2014-03-16T12:18:31.957 に答える