2010-04-14 2 views
5

Sono stato in giro con Leaks cercando di trovare quale funzione non è stata rilasciata (io sono ancora nuovo a questo) e potrebbe davvero usare qualche intuizione esperto.Come trovare il rubinetto che perde in Malloc 32kb

Ho questo bit di codice che sembra essere il colpevole. Ogni volta che preme il pulsante che chiama questo codice, 32kb di memoria vengono allocati alla memoria e quando viene rilasciato il pulsante la memoria non viene deallocata.

Quello che ho trovato è che ogni volta che AVAudioPlayer è chiamata a svolgere un file m4a, la funzione finale per analizzare il file m4a è MP4BoxParser::Initialize() e questo a sua volta alloca 32kb di memoria attraverso Cached_DataSource::ReadBytes

La mia domanda è, come si fa Vado su deallocating che dopo che è finito in modo che non continua a allocare 32kb ogni volta che viene premuto il pulsante?

Qualsiasi aiuto che potresti fornire è molto apprezzato!

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

//stop playing 
theAudio.stop; 


// cancel any pending handleSingleTap messages 
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleSingleTap) object:nil]; 

UITouch* touch = [[event allTouches] anyObject]; 


NSString* filename = [g_AppsList objectAtIndex: [touch view].tag]; 

NSString *path = [[NSBundle mainBundle] pathForResource: filename ofType:@"m4a"]; 
theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]; 
theAudio.delegate = self; 
[theAudio prepareToPlay]; 
[theAudio setNumberOfLoops:-1]; 
[theAudio setVolume: g_Volume]; 
[theAudio play]; 
} 

risposta

2

Il trucco per la gestione della memoria in Cocoa è bilanciare eventuali chiamate a alloc, retain o copy con una chiamata successiva a release.

In questo caso, si invia alloc per inizializzare la variabile theAudio, ma non si invia mai release.

Supponendo che si eseguirà un solo suono alla volta, il modo migliore per farlo è con una proprietà sul controller (quella con questo metodo -touchesBegan). La dichiarazione di proprietà sarebbe simile a questa:

@property (nonatomic, retain) AVAudioPlayer * theAudio; 

Sarà quindi necessario impostare theAudio a nil nel init metodo:

theAudio = nil; // note: simple assignment is preferable in init 

Ed essere sicuri di rilasciare la variabile nel metodo dealloc:

[theAudio release]; 

Ora, il tuo touchesBegan potrebbe essere simile al seguente:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    //stop playing 
    theAudio.stop; 
    ... 
    AVAudioPlayer * newAudio = [[AVAudioPlayer alloc] initWithContentsOfUrl:...]; 
    self.theAudio = newAudio; // it is automatically retained here... 

    theAudio.delegate = self; 
    [theAudio prepareToPlay]; 
    [theAudio setNumberOfLoops:-1]; 
    [theAudio setVolume: g_Volume]; 
    [theAudio play]; 

    [newAudio release];  // ...so you can safely release it here 
} 
+0

potresti spiegare quale metodo 'init' ti riferisci? (di nuovo, mi dispiace, sono molto nuovo a questo) – iwasrobbed

+0

e anche, solo per verificare, capisco questo: quello che stai dicendo è che ho bisogno di caricare l'audio in una variabile allocata aggiuntiva in modo che non stia cercando di deallocare l'attuale m4a file (o eventualmente chiamare un pezzo di memoria deallocato) Suppongo che la mia domanda sia, "l'audio" allocerà ancora memoria aggiuntiva ogni volta poiché non viene eseguita fino a quando non viene chiamato 'dealloc()'? – iwasrobbed

+0

Normalmente parlando, ogni controller ha sia un metodo '-init' che un metodo' dealloc'. Posso supporre che questo come un 'UIViewController'? In tal caso, il metodo corretto per eseguire l'override è -initWithNibName: bundle: un'altra alternativa consiste nel impostare ivar su nil nel metodo 'viewDidLoad'. –

1

Questa linea sembra colpevole a me:

theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]; 

Quando si fa questa risorsa ottenere rilasciato?