title: iphone: Help with AudioToolbox Leak: Stack trace/code included here
body: <p>Part of this app is a "Scream" button that plays random screams from cast members of a TV show.  I have to bang on the app quite a while to see a memory leak in Instruments, but it's there, occasionally coming up (every 45 seconds to 2 minutes.) The leak is 3.50kb when it occurs. Haven't been able to crack it for several hours. Any help appreciated.</p>
  
  <p>Instruments says this is the offending code line:</p>
  
  <pre><code>[appSoundPlayer play]; 
  </code></pre>
  
  <p>that's linked to from line 9 of the below stack trace:</p>
  
  <blockquote>
    <p>0 libSystem.B.dylib malloc<br>
       1 libSystem.B.dylib pthread_create<br>
       2 AudioToolbox CAPThread::Start()<br>
       3 AudioToolbox GenericRunLoopThread::Start()<br>
       4 AudioToolbox AudioQueueNew(bool, AudioStreamBasicDescription const*, TCACallback const&amp;, CACallbackTarget const&amp;, unsigned long, OpaqueAudioQueue**)<br>
       5 AudioToolbox AudioQueueNewOutput<br>
       6 AVFoundation allocAudioQueue(AVAudioPlayer*, AudioPlayerImpl*)<br>
       7 AVFoundation prepareToPlayQueue(AVAudioPlayer*, AudioPlayerImpl*)<br>
       8 AVFoundation -[AVAudioPlayer prepareToPlay]<br>
       9 Scream Queens -[ScreamViewController scream:] /Users/laptop2/Desktop/ScreamQueens Versions/ScreamQueens25/Scream Queens/Classes/../ScreamViewController.m:210<br>
      10 CoreFoundation -[NSObject performSelector:withObject:withObject:]<br>
      11 UIKit -[UIApplication sendAction:to:from:forEvent:]<br>
      12 UIKit -[UIApplication sendAction:toTarget:fromSender:forEvent:]<br>
      13 UIKit -[UIControl sendAction:to:forEvent:]<br>
      14 UIKit -[UIControl(Internal) _sendActionsForEvents:withEvent:]<br>
      15 UIKit -[UIControl touchesEnded:withEvent:]<br>
      16 UIKit -[UIWindow _sendTouchesForEvent:]<br>
      17 UIKit -[UIWindow sendEvent:]<br>
      18 UIKit -[UIApplication sendEvent:]<br>
      19 UIKit _UIApplicationHandleEvent<br>
      20 GraphicsServices PurpleEventCallback<br>
      21 CoreFoundation CFRunLoopRunSpecific<br>
      22 CoreFoundation CFRunLoopRunInMode<br>
      23 GraphicsServices GSEventRunModal<br>
      24 UIKit -[UIApplication _run]<br>
      25 UIKit UIApplicationMain<br>
      26 Scream Queens main /Users/laptop2/Desktop/ScreamQueens Versions/ScreamQueens25/Scream Queens/main.m:14<br>
      27 Scream Queens start  </p>
  </blockquote>
  
  <p>Here's .h:</p>
  
  <pre><code>#import &lt;UIKit/UIKit.h&gt;
  #import &lt;AVFoundation/AVFoundation.h&gt;
  #import &lt;MediaPlayer/MediaPlayer.h&gt;
  #import &lt;AudioToolbox/AudioToolbox.h&gt;
  #import &lt;MessageUI/MessageUI.h&gt;
  #import &lt;MessageUI/MFMailComposeViewController.h&gt;
  
  @interface ScreamViewController : UIViewController &lt;UIApplicationDelegate,        AVAudioPlayerDelegate, MFMailComposeViewControllerDelegate&gt; {
  
  
  
  
  
  //AudioPlayer related
  AVAudioPlayer           *appSoundPlayer;
  NSURL                   *soundFileURL;
  BOOL                    interruptedOnPlayback;
  BOOL                    playing;
  
  //Scream button related
  IBOutlet UIButton       *screamButton;
  int                     currentScreamIndex;
  NSString                *currentScream;
  NSMutableArray          *screams;
  NSMutableArray          *personScreaming;
  NSMutableArray          *photoArray;
  int                     currentSayingsIndex;
  NSString                *currentButtonSaying;
  NSMutableArray          *funnyButtonSayings;
  IBOutlet UILabel        *funnyButtonSayingsLabel;
  IBOutlet UILabel        *personScreamingField;
  IBOutlet UIImageView    *personScreamingImage;
  
  
  
  //Mailing the scream related
      IBOutlet UILabel        *mailStatusMessage;
      IBOutlet UIButton       *shareButton;
  
  
  }
  //AudioPlayer related
  @property (nonatomic, retain)   AVAudioPlayer                   *appSoundPlayer;
  @property (nonatomic, retain)   NSURL                           *soundFileURL;
  @property (readwrite)           BOOL                            interruptedOnPlayback;
  @property (readwrite)           BOOL                            playing;
  
  //Scream button related
  @property (nonatomic, retain)   UIButton                        *screamButton;
  @property (nonatomic, retain)   NSMutableArray                  *screams;
  @property (nonatomic, retain)   NSMutableArray                  *personScreaming;
  @property (nonatomic, retain)   NSMutableArray                  *photoArray;
  @property (nonatomic, retain)   UILabel                         *personScreamingField;
  @property (nonatomic, retain)   UIImageView                     *personScreamingImage;
  @property (nonatomic, retain)   NSMutableArray                  *funnyButtonSayings;
  @property (nonatomic, retain)   UILabel                         *funnyButtonSayingsLabel;
  
  
  //Mailing the scream related
  @property (nonatomic, retain) IBOutlet UILabel                  *mailStatusMessage;
  @property (nonatomic, retain) IBOutlet UIButton                 *shareButton;
  
  
  //Scream Button
  - (IBAction)    scream:                 (id) sender;
  
  //Mail the scream
  - (IBAction) showPicker:    (id)sender;
  - (void)displayComposerSheet;
  - (void)launchMailAppOnDevice;
  
  
  @end
  </code></pre>
  
  <p>Here's the top of .m:</p>
  
  <pre><code>#import "ScreamViewController.h"
  
  //top of code has Audio session callback function for responding to audio route changes (from Apple's code), then my code continues...
  
  @implementation ScreamViewController 
  
  @synthesize appSoundPlayer;             // AVAudioPlayer object for playing the selected scream
  @synthesize soundFileURL;               // Path to the scream
  @synthesize interruptedOnPlayback;      // Was application interrupted during audio playback
  @synthesize playing;                    // Track playing/not playing state
  
  
  @synthesize screamButton;               //Press this button, girls scream.
  @synthesize screams;                    //Mutable array holding strings pointing to sound files of screams.
  @synthesize personScreaming;            //Mutable array tracking the person doing the screaming
  @synthesize photoArray;                 //Mutable array holding strings pointing to photos of screaming girls
  @synthesize personScreamingField;       //Field updates to announce which girl is screaming.
  @synthesize personScreamingImage;       //Updates to show image of the screamer.
  @synthesize funnyButtonSayings;         //Mutable array holding the sayings
  @synthesize funnyButtonSayingsLabel;    //Label that updates with the funnyButtonSayings
  
  
  @synthesize mailStatusMessage;          //did the email go out
  @synthesize shareButton;                //share scream via email
  </code></pre>
  
  <p>Next line begins the block with the offending code:</p>
  
  <pre><code>- (IBAction) scream: (id) sender
  {
      //Play a click sound effect
      SystemSoundID soundID;
      NSString *sfxPath = [[NSBundle mainBundle]
                           pathForResource:@"aClick" ofType:@"caf"];    
  
      AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:sfxPath],&amp;soundID);
      AudioServicesPlaySystemSound (soundID); 
  
  
      // Because someone may slam the scream button over and over, 
      //must stop current sound, then begin next  
      if ([self appSoundPlayer] != nil)
      {
          [[self appSoundPlayer] setDelegate:nil];
          [[self appSoundPlayer] stop];
          [self setAppSoundPlayer: nil];
  
      }
  
  
      //after selecting a random index in the array (did that in View Did Load), 
      //we move to the next scream on each click. 
  
      //First check...
      //Are we past the end of the array?
  
      if (currentScreamIndex == [screams count]) 
      {
          currentScreamIndex = 0;
      }
  
  
      //Get the string at the index in the personScreaming array
  
      currentScream = [screams objectAtIndex: currentScreamIndex]; 
  
  
      //Get the string at the index in the personScreaming array
      NSString *screamer = [personScreaming objectAtIndex:currentScreamIndex];
  
      //Log the string to the console
      NSLog (@"playing scream: %@", screamer);
  
      // Display the string in the personScreamingField field
      NSString *listScreamer = [NSString stringWithFormat:@"scream by: %@", screamer];
  
      [personScreamingField setText:listScreamer];
  
  
      // Gets the file system path to the scream to play.
      NSString *soundFilePath = [[NSBundle mainBundle]    pathForResource:    currentScream
                                                                ofType:               @"caf"];
  
      // Converts the sound's file path to an NSURL object
      NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
      self.soundFileURL = newURL;
      [newURL release];
      [[AVAudioSession sharedInstance] setDelegate: self];
      [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
  
      // Registers the audio route change listener callback function
      AudioSessionAddPropertyListener (
                                       kAudioSessionProperty_AudioRouteChange,
                                       audioRouteChangeListenerCallback,
                                       self
                                       );
  
      // Activates the audio session.
  
      NSError *activationError = nil;
      [[AVAudioSession sharedInstance] setActive: YES error: &amp;activationError];
  
      // Instantiates the AVAudioPlayer object, initializing it with the sound
      AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];
  
      //Error check and continue
      if (newPlayer != nil)
      {
          self.appSoundPlayer = newPlayer;
          [newPlayer release];
          [appSoundPlayer prepareToPlay];
          [appSoundPlayer setVolume: 1.0];
          [appSoundPlayer setDelegate:self];
          //NEXT LINE IS FLAGGED BY INSTRUMENTS AS LEAKY
          [appSoundPlayer play];
          playing = YES;
  
  
  
          //Get the string at the index in the photoArray array
          NSString *screamerPic = [photoArray objectAtIndex:currentScreamIndex];
  
          //Log the string to the console
          NSLog (@"displaying photo: %@", screamerPic);
  
          // Display the image of the person screaming
          personScreamingImage.image = [UIImage imageNamed:screamerPic];
  
          //show the share button
          shareButton.hidden = NO;
  
          mailStatusMessage.hidden = NO;
          mailStatusMessage.text = @"share!";
  
  
  
          //Get the string at the index in the funnySayings array
          currentSayingsIndex = random() % [funnyButtonSayings count];
          currentButtonSaying = [funnyButtonSayings objectAtIndex: currentSayingsIndex]; 
  
          NSString *theSaying = [funnyButtonSayings objectAtIndex:currentSayingsIndex];
          [funnyButtonSayingsLabel setText: theSaying];
  
          currentScreamIndex++;
  
  
  
      }
  }
  </code></pre>
  
  <p>Here's my dealloc:</p>
  
  <pre><code>- (void)dealloc {
      [appSoundPlayer stop];
      [appSoundPlayer release], appSoundPlayer = nil;
      [screamButton release], screamButton = nil;
      [mailStatusMessage release], mailStatusMessage = nil;
      [personScreamingField release], personScreamingField = nil;
      [personScreamingImage release], personScreamingImage = nil;
      [funnyButtonSayings release], funnyButtonSayings = nil;
      [funnyButtonSayingsLabel release], funnyButtonSayingsLabel = nil;
      [screams release], screams = nil;
      [personScreaming release], personScreaming = nil;
      [soundFileURL               release];
  
      [super dealloc];
  }
  
  
  @end
  </code></pre>
  
  <p>Thanks so much for reading this far! Any input appreciated.</p>