I have this method in a开发者_C百科n 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];
}
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
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
AVAudioPlayer memory leak
AVAudioPlayer Memory Leak - Media Player Framework
Here is the blog post
AVAudioPlayer Memory Leak
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.
精彩评论