I have an app that connects to an accessory, and the EASession that I create in order to communicate with the accessory leaks when you disconnect the accessory.
When the accessory connects, I get a notification of this and check EAAccessoryManager's accessories collection for an accessory with a certain name that uses a certain protocol. When I find this I create an EASession object for that 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;
}
}
Normally I have the alloc and init on one line, but what I've found (separating it out like this) is that the alloc gives +1 retain count (as you'd expect) BUT the iniWithAccessory:forProtocol:
gives it +3 retain count when I would only expect +2 retainCount from the init method.
The leaks instrument also appears to support this:
Step by Step look at the leaks instrument:
- +1 retain count ::
[???Accessory openSession]
- this is where I alloc a new EASession. - +1 retain count ::
[EAInputStream iniWithAccessory:forSession:]
The input stream holds a reference back to the owning session. - +1 retain count ::
[EAOutputStream initWithAccessory:forSession:]
The output stream holds a reference back to the owning session. - +1 retain count ::
[EASession iniWithAccessory:forProtocol:]
I have no idea why this is increasing the retain count of EASession. I believe this is responsible for the additional retain count that I can't account for... Not sure how this is supposed to be balanced. Is this Apple's bug and I need to callrelease
an extra time to balance things.... Very VERY weird. - -1 retain count ::
[EAInputStream close]
Cleans up step #2 above - -1 retain count ::
[EAOutputStream close]
Cleans up step #3 above - -1 retain count ::
???Accessory closeSession]
Cleans up step #1 above1
So... Why am I leaking the EASession object? What's the proper way to use a EASession object to not leak?
Edit - EADemo Does Not Leak, but ...
EADemo connects to accessories, but it does not leak. Out of curiosity, I added an extra [_session retain]
to make it leak so I could follow the malloc history of it in instruments. It was interesting to see some internal things called that were not called in the malloc history of my app.
You can see this has [EAAccessoryInternal removeSession:]
called 3 times. This was never called in the malloc history of my app. I think this is key to why my EASession is not being released...
alloc
andinit
, you might want to read the answers to this question: Why in Objective-C does doing alloc and init in separate statements cause the object to be released according to the Xcode static analyzer?. While possibly unrelated, splitting these two is not recommended for the reasons discussed there. – Plessalloc
andinitWithAccessory:forProtocol:
, but before releasing theEASession
has a retain count of 1... So I'm doing something wrong. – Ageratum