Reputation: 1293
Having a really hard time hunting this one down. A production app is crashing intermittently (~2% of users). It's a card game so there is a lot of tapping on cards. Whenever you tap on a card it makes a sound. The crash happens seemingly randomly, but I can reproduce by tapping on cards for a while and then randomly it will just crash.
It's not possible to reproduce reliably, but after long sessions using Instruments/Zombies I see that the Zombie object is an AVAudioPlayer
object. It is a simple card game app (not done using SK or any other game framework--all UIKit/normal Objective C). I'm using a very straightforward implementation of AVAudioPlayer
. All details below.
Stack Trace:
Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x206270d70 objc_msgSend + 16
1 Foundation 0x207b3d42c __NSThreadPerformPerform + 336
2 CoreFoundation 0x20701a0e0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
3 CoreFoundation 0x20701a060 __CFRunLoopDoSource0 + 88
4 CoreFoundation 0x207019944 __CFRunLoopDoSources0 + 176
5 CoreFoundation 0x207014810 __CFRunLoopRun + 1040
6 CoreFoundation 0x2070140e0 CFRunLoopRunSpecific + 436
7 GraphicsServices 0x20928d584 GSEventRunModal + 100
8 UIKitCore 0x2343a8c00 UIApplicationMain + 212
9 <app name> 0x1007930f0 main (main.m:14)
10 libdyld.dylib 0x206ad2bb4 start + 4
AppDelegate.m didFinishLaunchingWithOptions
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
BOOL success = [[AVAudioSession sharedInstance] setActive:YES error:nil];
ViewController.h
@property (strong, nonatomic) AVAudioPlayer *audioPlayer;
ViewController.m
-(void) playSound:(NSString *) strSoundName {
NSString *fileName = @"Move_1";
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"aif"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
float volume = 0.5;
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
[self.audioPlayer setVolume:volume];
[self.audioPlayer play];
}
AVAudioPlayer Reference History
handleTap:::
is the method that calls playSound
Upvotes: 2
Views: 168
Reputation: 1293
Was never able to figure out exactly why it was crashing randomly.
However, we were able to resolve the issue by initializing the AVAudioPlayer
once in viewDidLoad
and then just call play
in that method (instead of initializing every time we wanted to play the sound).
Upvotes: 0
Reputation: 3028
You've done a pretty fantastic job debugging here. Most people get very tripped up by memory management/heap corruption bugs, like this one.
There is, however, a clue in that Instruments trace that you need to investigate: the zombie turns up just after a performSelector
call. This makes me think that a pointer to your view controller, or to the AVAudioPlayer instance itself, is being referenced in the code that performSelector
invokes. Since this code is running after the view controller has been deallocated, you get your dangling pointer.
For starters, I'd look more closely at what handleTap:::
is doing. Are you invoking performSelector
there? And, if so, take a close look at what instances you are using for it. If not, audit your uses of performSelector
in other places to see if somehow a plain pointer could be captured to your view controller or AVAudioPlayer instance.
Upvotes: 1