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:
[???Accessory openSession]
- this is where I alloc a new EASession.[EAInputStream iniWithAccessory:forSession:]
The input stream holds a reference back to the owning session.[EAOutputStream initWithAccessory:forSession:]
The output stream holds a reference back to the owning session.[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 call release
an extra time to balance things.... Very VERY weird.[EAInputStream close]
Cleans up step #2 above[EAOutputStream close]
Cleans up step #3 above???Accessory closeSession]
Cleans up step #1 above1So... Why am I leaking the EASession object? What's the proper way to use a EASession object to not leak?
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...
I know this discussion is quite old now but I had exactly the same problem recently using ARC e.t.c. I've found that one way around it is by just not closing the input or output streams. Just have a class that deals with all input e.t.c and forward on the data on request to other parts of your application. You can re-alloc init the EASession object with no complaints from XCode so I'm assuming the old EASession is dealloc ed OK as it's no longer referenced by my APP. I haven't checked the leaks yet however.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With