Reputation: 3108
I have this method in an exterior class that gets called whenever the charachter in my game hits a wall (about once every 5 seconds on average). I dont understand it. I thaught I was on top of the memory management. Everytime the method is called, a small amount of memory is leaked (Malloc 38 or 42 bytes) This keeps happening, and the game freezes up. Here is my code:
-(void)playBoing {
int x = (arc4random()%3)+1;
NSString *path = [NSString stringWithFormat:@"/boing_0%i.aif", x];
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
resourcePath = [resourcePath stringByAppendingString:path];
if (boing != nil) {
boing = nil;
boing.delegate = nil;
[boing release];
}
boing = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath] error:nil];
boing.delegate = self;
boing.volume = 1;
[boing play];
}
Upvotes: 0
Views: 1446
Reputation: 2230
Of course, it's lead to memory leak
First you said, that boing is nil (but memory is not deallocated, leaked), then trying to send release message to nil. You should do it like this:
[boing release];
boing = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath] error:nil];
No need to check boing for nil before releasing, because sending message to nil do nothing
Upvotes: 1
Reputation: 31722
I think, the below statement is the source of memory leak,
player = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:&err];
Here is the SO posts which has discussed the same issue.
AVAudioPlayer Memory Leak - Media Player Framework
Here is the blog post
As per the blog tutorial your code must be look like below.
-(void)setPlayer
{
NSURL *file = [[NSURL alloc] initFileURLWithPath:
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"shut up.mp3"]];
NSError *err = nil;
NSData *data = [NSData dataWithContentsOfFile:file];
AVAudioPlayer *player = [AVAudioPlayer alloc];
if([player initWithData:audioData error:NULL])
{
player.numberOfLoops = -1;
[player prepareToPlay];
player.volume=1.0;
[player autorelease];
}
else
{
[player release];
player = nil;
}
[file release];
}
The leak-free version stores the pointer returned by alloc, rather than the pointer returned by initWithData:error:. That way, whatever happens, the player can still be released.
Upvotes: 1