I have an application that connects to an accessory, and an EASession that I create to connect with accessory leaks when disconnecting the accessory.
When an accessory is connected, I receive a notification about this and check the EAAccessoryManager accessory collection for the accessory with a specific name that uses a specific protocol. When I find this, I create an EASession object for this accessory with code:
-(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; } }
Usually I have alloc and init on the same line, but what I found (dividing it like this) is that alloc gives +1 to keep the score (as you would expect) BUT iniWithAccessory:forProtocol:
gives it a hold value + 3 when I would expect +2 saveCount from the init method.
The leak tool also supports this:
A step-by-step look at the leak tool:
- +1 save count ::
[???Accessory openSession]
- here I highlight the new EASession. - +1 save count ::
[EAInputStream iniWithAccessory:forSession:]
The input stream returns a link to the ownership session. - +1 save count ::
[EAOutputStream initWithAccessory:forSession:]
The output stream returns a link to the ownership session. - +1 keep count ::
[EASession iniWithAccessory:forProtocol:]
I have no idea why this increases the number of EASession accounts. I believe that this is responsible for an additional retention rate, which I canโt explain ... Not sure how it should be balanced. Is this Apple's mistake, and I need to call release
extra time to balance things ... Very VERY weird. - -1 count count ::
[EAInputStream close]
Clears step # 2 above - -1 count count ::
[EAOutputStream close]
Clears step # 3 above - -1 count count ::
???Accessory closeSession]
Clears step # 1 above1
So ... Why am I leaking an EASession object? What is the correct way to use an EASession object to leak?
Edit - EADemo is not a leak, but ...
EADemo connects to accessories, but it does not flow. Out of curiosity, I added an extra [_session retain]
so that it leaked so that I could follow its history in tools. It was interesting to see some internal things that were not mentioned in the malloc history of my application.
You can see that it has [EAAccessoryInternal removeSession:]
called 3 times. This has never been called up in the malloc history of my application. I think this is the key to why my EASession is not released ...
source share