이 앱의 일부는 TV 프로그램의 출연진으로부터 임의의 비명 소리를 재생하는 "비명 소리"버튼입니다. 인스 트루먼 트에서 메모리 누수를보기 위해 꽤 오랜 시간이 걸렸지 만 가끔씩 (45 초에서 2 분마다) 올라옵니다. 누출은 3.50kb입니다. 몇 시간 동안 깨지 못했습니다. 어떤 도움을 주셔서 감사합니다.iphone : AudioToolbox 도움말 누출 : 여기에 포함 된 스택 추적/코드
Instruments는이 문제가되는 코드 라인 말합니다 :
0 libSystem.B.dylib의 malloc에
1 libSystem : 아래 스택 트레이스 라인 (9)에 링크 것[appSoundPlayer play];
. B.dylib pthread_create
2 오디오 도구 상자 CAPThread :: Start()
3 AudioToolbox GenericRunLoopThread :: Start()
,4 AudioToolbox AudioQueueNew (BOOL, AudioStreamBasicDescription의 CONST *를 TCACallback의 CONST &, CACallbackTarget의 CONST &, 부호 길이 OpaqueAudioQueue **)
5 AudioToolbox AudioQueueNewOutput
6 AVFoundation allocAudioQueue (AVAudioPlayer * AudioPlayerImpl *)
7 AVFoundation prepareToPlayQueue (AVAudioPlayer * AudioPlayerImpl *)
8 AVFoundation - [AVAudioPlayer prepareToPlay은]
9 비명 퀸즈 - [ScreamViewController 비명 :]/사용자/laptop2/데스크탑/스크림 퀸스 버전/ScreamQueens25/스크림 퀸즈/클래스 /../ ScreamViewController.m을 : (210)
10 CoreFoundation - [N SObject performSelector : withObject : withObject :]
11 UIKit - [UIApplication 액션 (SendAction) : 행 : 행 : forEvent :]
12 UIKit - [UIApplication 액션 (SendAction) : toTarget : fromSender : forEvent :]
13 UIKit - [UIControl 액션 (SendAction) 님 : forEvent :]
14 UIKit - [UIControl (내부) _sendActionsForEvents : withEvent :]
15 UIKit - [UIControl touchesEnded : withEvent :]
16 UIKit - [UIWindow _sendTouchesForEvent :]
17 UIKit - [UIWindow sendEvent : ]
18 UIKit - [UIApplication sendEvent :]
19 [UIApplication _run]
25 UIKit UIApplicationMain
26 스크림 퀸스 메인/사용자/laptop2/화상/스크림 퀸스 - UIKit _UIApplicationHandleEvent
20 GraphicsServices는
21 CoreFoundation에서 CFRunLoopRunSpecific
22 CoreFoundation에서의 CFRunLoopRunInMode
23 GraphicsServices GSEventRunModal
24 UIKit을 PurpleEventCallback 버전/ScreamQueens25/비명 퀸즈/main.m : 14
27 비명 퀸즈 스타트
여기 .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
여기의 상단입니다.남 :
#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
다음 줄은 잘못된 코드 블록을 시작 : 지금이 글을 읽고에 대한
- (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
정말 고마워요 :
- (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++;
}
}
여기 내의 dealloc입니다! 모든 의견을 감사드립니다.
Rab, 고마워요! 당신의 추측이 내가 가진 2 가지 문제 중 일부였던 것 같습니다. 나는 나의 아울렛 2의 유지 수, 현재 컨트롤러와 수퍼했다 몰랐어요. 뷰가 "멈춰"메모리가 부족하다는 경고를 받았을 때 메모리가 누수되고 뷰가 언로드되지만 올바르게 할당이 해제되지 않았습니다. 내 viewDidUnload 및 dealloc을 변경하면 다음과 같이 표시됩니다. - (void) viewDidUnload { \t [appSoundPlayer release], appSoundPlayer release = [super viewDidUnload]; } - (void) dealloc { \t [appSoundPlayer release]; \t [super dealloc]; } –
다행히 해결되었습니다. – Rab