iphone: Помощь с AudioToolbox Leak: трассировка стека / код включены здесь - PullRequest
0 голосов
/ 01 июня 2010

Частью этого приложения является кнопка «Scream», которая воспроизводит случайные крики от актеров телевизионного шоу.Мне нужно довольно долго глядеть в приложение, чтобы увидеть утечку памяти в Instruments, но она есть, иногда появляется (каждые 45 секунд - 2 минуты). Утечка составляет 3,50 КБ, когда она возникает.Не удалось взломать его в течение нескольких часов.Любая помощь приветствуется.

Instruments сообщает, что это неправильная строка кода:

[appSoundPlayer play]; 

, которая связана со строкой 9 приведенной ниже трассировки стека:

0libSystem.B.dylib malloc
1 libSystem.B.dylib pthread_create
2 AudioToolbox CAPThread :: Start ()
3 AudioToolbox GenericRunLoopThread :: Start ()
4 AudioToolbox AudioQueueNew (bool, AudioStreamBest), TCACallback const &, CACallbackTarget const &, длинная беззнаковая, OpaqueAudioQueue **)
5 AudioToolbox AudioQueueNewOutput
6 AVFoundation allocAudioQueue (AVAudioPlayer *, AudioPlayerImpl * Подготовка к аудио *AVFoundation - [AVAudioPlayer prepareToPlay]
9 Scream Queens - [ScreamViewController scream:] / Пользователи / ноутбук2 / Рабочий стол / Версии ScreamQueens / ScreamQueens25 / Scream Queens / Классы /../ ScreamViewController.m: 210
10 CoreFoundation - [NSObject executeSelector: withObject: withObject:]
11 UIKit - [UIApplication sendAction: to: from: forEvent:]
12 UIKit - [UIApplication sendAction: toTarget: fromSender: forEvent:]
13 UIKit - [UIControl sendAction: to: forEvent:]
14 UIKit - [UIControl(Внутреннее) _sendActionsForEvents: withEvent:]
15 UIKit - [UIControl touchsnded: 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 графических сервисов GSEventRun для использования с ПО для организации работы с графическим интерфейсом 23 UIKUIUIUIUIUIUKIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUIUI - UIUI - UI, UI, UI, UI, UI, UI, UI, Application, UI, UI, Application, UI, UI, Application. Также.
26 Scream Queens main / Пользователи / ноутбук2 / Рабочий стол / Версии ScreamQueens / ScreamQueens25 / Scream Queens / main.m: 14
27 запуск Scream Queens

Вот .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

Вот вершина .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

Следующая строка начинает блок с кода ошибки:

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



    }
}

Вот моя сделка:

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

Большое спасибо за чтение этого!Любой вклад приветствуется.

1 Ответ

3 голосов
/ 14 июня 2010

Возможно, это красная сельдь из инструмента "Утечки". Смотрите это сообщение на форумах разработчиков: https://devforums.apple.com/message/119423#119423 Я "обнаруживаю" ту же утечку в инструменте утечек в моей реализации AVAudioPlayer и почти уверен, что мой код корректен (в основном потому, что он очень прост). Вот фактический комментарий эксперта; он говорит о 3.5k, обнаруженных в [NSThread start], и у нас здесь есть 3.5k [CAPThread :: Start ()], но я думаю, что мы в одной лодке:

"Проблема в том, что 3.5K, которые вы видите, - это в основном структура данных, необходимая для ядра, чтобы отслеживать поток. Эта структура данных будет в конечном итоге освобождена, но как только поток завершится, ссылка на него больше не будет пространство вашего процесса (только в ядре). "

Надеюсь, это поможет.

...