2010-06-01 25 views
0

Une partie de cette application est un bouton "Scream" qui joue des cris au hasard des membres de la distribution d'une émission de télévision. Je dois bang sur l'application assez longtemps pour voir une fuite de mémoire dans les instruments, mais il est là, occasionnellement à venir (toutes les 45 secondes à 2 minutes.) La fuite est de 3.50kb quand il se produit. Je n'ai pas réussi à le casser pendant plusieurs heures. Toute aide appréciée.iphone: Aide avec AudioToolbox Leak: Stack trace/code inclus ici

Instruments dit ceci est la ligne de code en question:

[appSoundPlayer play]; 

qui est lié à partir de la ligne 9 de la trace de pile ci-dessous:

0 libSystem.B.dylib malloc
1 libSystem. B.dylib pthread_create
2 AudioToolbox CAPThread :: Démarrer()
3 AudioToolbox GenericRunLoopThread :: Démarrer()
4 AudioToolbox AudioQueueNew (bool, AudioStreamBasicDescription const *, TCACallback const &, CACallbackTarget const &, unsigned long, OpaqueAudioQueue **)
5 AudioToolbox AudioQueueNewOutput
6 AVFoundation allocAudioQueue (AVAudioPlayer *, AudioPlayerImpl *)
7 AVFoundation prepareToPlayQueue (AVAudioPlayer *, * AudioPlayerImpl)
8 AVFoundation - [AVAudioPlayer prepareToPlay]
9 Cri Queens - [ScreamViewController cri:]/Users/laptop2/Desktop/scream Queens Versions/ScreamQueens25/Cri/Queens Classes /../ ScreamViewController.m: 210
10 CoreFoundation - [N SObject performSelector: withObject: withObject:]
11 UIKit - [UIApplication sendAction: à: à partir de: forEvent:]
12 UIKit - [UIApplication sendAction: toTarget: fromSender: forEvent:]
13 UIKit - [UIControl sendAction: à : forEvent:]
14 UIKit - [UIControl _sendActionsForEvents (interne): withEvent:]
15 UIKit - [UIControl touchesEnded: withEvent:]
16 UIKit - [UIWindow _sendTouchesForEvent:]
17 UIKit - [UIWindow sendEvent: ]
18 UIKit - [UIApplication sendEvent:]
19 UIKit _UIApplicationHandleEvent
20 GraphicsServices PurpleEventCallback
21 CoreFoundation CFRunLoopRunSpecific
22 CoreFoundation CFRunLoopRunInMode
23 GraphicsServices GSEventRunModal
24 UIKit - [UIApplication _run]
25 UIKit UIApplicationMain
26 Cri principal Queens/Users/laptop2/de bureau/Scream Queens Versions/ScreamQueens25/Scream Queens/main.m: 14
27 Scream Queens début

Voilà .h:

#import <UIKit/UIKit.h> 
#import <AVFoundation/AVFoundation.h> 
#import <MediaPlayer/MediaPlayer.h> 
#import <AudioToolbox/AudioToolbox.h> 
#import <MessageUI/MessageUI.h> 
#import <MessageUI/MFMailComposeViewController.h> 

@interface ScreamViewController : UIViewController <UIApplicationDelegate,  AVAudioPlayerDelegate, MFMailComposeViewControllerDelegate> { 





//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 

Voici le haut de.m:

#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 

ligne suivante commence le bloc avec le code incriminé:

- (IBAction) scream: (id) sender 
{ 
    //Play a click sound effect 
    SystemSoundID soundID; 
    NSString *sfxPath = [[NSBundle mainBundle] 
         pathForResource:@"aClick" ofType:@"caf"];  

    AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:sfxPath],&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: &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++; 



    } 
} 

Voici mon dealloc:

- (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 

Merci beaucoup pour la lecture de loin! Toute contribution appréciée.

Répondre

3

Il est possible que ce soit un faux-fuyant de l'outil Fuites. Voir cet article dans les forums de développement: https://devforums.apple.com/message/119423#119423 Je "détecter" la même fuite dans l'outil de fuites dans ma mise en œuvre d'un AVAudioPlayer et suis assez sûr que mon code est correct (principalement parce que c'est si simple). Voici le commentaire d'expert actuel; il parle de 3.5k détecté à [démarrage NSThread] et nous avons ici un 3.5k [CAPThread :: Start()], mais je pense que nous sommes dans le même bateau:

"Le problème est que le 3.5K vous voyez, c'est essentiellement une structure de données nécessaire au noyau pour suivre un thread.Cette structure de données sera finalement libérée, mais une fois le thread terminé, il n'y a plus de référence dans votre espace de processus (seulement dans le noyau). "

J'espère que cela aide.

+0

Rab, Merci! On dirait que votre supposition était la partie 1 d'un problème de 2 parties que j'avais. Je ne me suis pas rendu compte que mes points de vente avaient un nombre de retenue de 2, le contrôleur actuel et l'aperçu. Je perdais seulement de la mémoire quand la vue «pendait», ce qui signifiait que je recevais un avertissement de faible mémoire, la vue était déchargée, mais pas correctement désallouée. Changer mon viewDidUnload et dealloc pour ressembler plus à ceci résolu: - (void) viewDidUnload { \t [appSoundPlayer version], appSoundPlayer = nil; [super viewDidUnload]; } - (vide) dealloc { \t [appSoundPlayer]; \t [super dealloc]; } –

+0

Content de l'avoir résolu! – Rab