Unable to troubleshoot severe memory leaks from Open AL
I am nearing the end of a large iPhone project and while checking for a memory leak I came across this huge one. I have implemented the sound after this tutorial:
http://www.gehacktes.net/2009/03/iphone-programming-part-6-multiple-sounds-with-openal/
A charm works, a lot of people use it, but I get a huge leak at the beginning of the project when the sound is initially loaded. Below are the lines of code that are starting to leak:
[[Audio sharedMyOpenAL] loadSoundWithKey:@"music" File:@"Music" Ext:@"wav" Loop:true];
[[Audio sharedMyOpenAL] loadSoundWithKey:@"btnPress" File:@"BtnPress" Ext:@"wav" Loop:false];
[[Audio sharedMyOpenAL] loadSoundWithKey:@"ting1" File:@"GlassTing1" Ext:@"wav" Loop:false];
etc .. etc. it is loaded in 20 sounds in total. And more specifically, in the Audio.m file, this piece of code:
+ (Audio*)sharedMyOpenAL {
@synchronized(self) {
if (sharedMyOpenAL == nil) {
sharedMyOpenAL = [[self alloc] init]; // assignment not done here
}
}
return sharedMyOpenAL;
}
I'm not sure how to fix this issue and any help on this would be greatly appreciated.
Thank.
source to share
Isn't the leak just syntax Audio
? I'm not sure how leak detection works, but from a certain point of view, most singletons are leaks as they only release memory after your application exits.
If this is the case, then it depends on whether the memory used by sounds needs to be freed. Memory usage shouldn't increase, so you don't have to worry about a "traditional leak" scenario where your application gets more and more memory until it is killed. The code you are using does not seem to support sound unloading, so if you want to free memory, you have to add that code yourself.
And a personal point of view: Writing a sound effect using a singleton is not a good design. Sound control becomes a pain (this is exactly the problem you are having), singleton adds a lot of unnecessary template code, etc. I see no reason why sounds shouldn't be simple separate objects with their own lifecycle - this is the way I've done it in my attempt at OpenAL SFX engine . Of course, I could be wrong.
Update: I believe the magic quest not done here is the key. The singleton code comes from Apple's documentation , but someone inserted an extra assignment. The method sharedFoo
should look like this:
+ (MyGizmoClass*)sharedManager
{
@synchronized(self) {
if (sharedGizmoManager == nil) {
[[self alloc] init]; // assignment not done here
}
}
return sharedGizmoManager;
}
When you do a secondary assignment self
, you create the leak you are looking for.
source to share