views:

279

answers:

1

Hi there! I'm nearing the end of a big iPhone project and whilst checking for memory leaks stumbled on this huge one. I implemented the sound following this tutorial:

http://www.gehacktes.net/2009/03/iphone-programming-part-6-multiple-sounds-with-openal/

Works a charm, a lot of people use it but I get a huge leak a start of the project when sound is initially loaded in. Below are the lines of code that start of the 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 loads in 20 sounds altogether. And more specifically in the Audio.m file this chunk of code:

+ (Audio*)sharedMyOpenAL {

@synchronized(self) {
    if (sharedMyOpenAL == nil) {
        sharedMyOpenAL = [[self alloc] init]; // assignment not done here

    }
}
return sharedMyOpenAL;
}

I am unsure how to resolve this and any help on the matter would be greatly appreciated.

Thanks.

+2  A: 

Isn’t the “leak” simply the Audio singleton? I am not sure how the leak detection works, but from a certain viewpoint most singletons are leaks, since they only release memory after your application exits.

If this really is the case, then it depends on whether you need to release the memory used by the sounds. The memory usage should not go up, so you don’t have to worry about the “traditional leak” scenario where your application takes more and more memory until it gets killed. The code you are using does not seem to support sound unloading, so that if you want to release the memory, you’ll have to add that code yourself.

And a personal viewpoint: Writing a sound effect engine using a singleton is not a good design. Managing the sounds becomes a pain (this is exactly the problem you are facing), the singleton adds a lot of unnecessary boilerplate code, etc. I see no reason the sounds should not be simple separate objects with their own lifecycle – this is the way I’ve done it in my attempt at an OpenAL SFX engine. Of course, I could be wrong.


Update: I suppose the magic ‘assignment not done here’ is the key. The singleton code is taken from the Apple documentation, but somebody inserted an extra assignment. The sharedFoo method should look like this:

+ (MyGizmoClass*)sharedManager
{
    @synchronized(self) {
        if (sharedGizmoManager == nil) {
            [[self alloc] init]; // assignment not done here
        }
    }
    return sharedGizmoManager;
}

When you perform the extra assignment to self, you create the leak you are looking for.

zoul
Hi zoul thanks for reply. By the sounds of things I can't get rid of it then without using a new set of code. I had a look at yours, when I ran it using instruments I found a leak at:[Finch initOpenAL];Is this something you have resolved yet?
There should be no leak, the code is quite simple. If you simply call `[[Finch alloc] init]` without saving the new instance into a variable, you get a leak, of course. You can ignore the leak, since it’s pretty harmless, or (better) simply save the instance into a variable and release it when your application ends.
zoul
But before you start tearing out your old code you should make sure you understand what is going on. Maybe I am wrong and there is a simple way to fix your code.
zoul
I tried that and it still leaked, I tore my hair our for a bit, went home, came back to the office today, tried it again and now we are leak free! Not sure what I did the first time haha but that does seem to have cleared it up, thanks very much for your help :)