2009-08-29 61 views
6

Tôi bị kẹt trên một số vấn đề rò rỉ bộ nhớ lạ liên quan đến AVAudioPlayer và tôi cần trợ giúp sau khi thử mọi thứ mà bạn nghĩ đến.Rò rỉ bộ nhớ AVAudioPlayer

Đây là mô tả ngắn về vấn đề - mã xuất hiện ngay sau đó. Tôi khởi tạo trình phát của mình và bắt đầu phát bản âm thanh trong vòng lặp vô tận (và vòng lặp vô tận hoặc phát một lần không làm thay đổi vấn đề). Vài giây sau khi nhạc bắt đầu, tôi chuyển sang một bản nhạc khác, do đó tôi tạo một trình phát mới, khởi chạy nó, phát hành bản nhạc cũ (đang phát) và sau đó cài đặt bản nhạc mới và phát.

Vào thời điểm đó (ngay sau khi tôi gọi Trình phát mới - [Trình phát], tôi bị rò rỉ bộ nhớ (3,5Kb).

tôi thử như sau:

  • Dừng các cầu thủ cũ và sau đó phát hành nó - không có tác dụng

  • phát hành Player ngay sau khi hướng dẫn chơi - không chơi bắt đầu

  • Phát hành hai lần trình phát cũ - lỗi

  • Rò rỉ bộ nhớ KHÔNG xảy ra khi tôi tạo và phát Người chơi đầu tiên!

Ngoài ra, trong các tài liệu tham khảo nó nói rằng 'chơi' là async và do đó có thể làm tăng số lượng ref bằng 1, nhưng trong trường hợp này, tại sao không [chơi dừng lại] giúp?

Cảm ơn,

Dưới đây là một số bộ phận của mã về cách tôi sử dụng nó:

- (void) loadAndActivateAudioFunction { 
NSBundle  *mainBundle = [NSBundle mainBundle]; 
NSError   *error; 
NSURL   *audioURL = [NSURL fileURLWithPath:[mainBundle pathForResource: Name ofType: Type]]; 
AVAudioPlayer *player = [(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error]; 

if (!player) { 
    DebugLog(@"Audio Load Error: no Player: %@", [error localizedDescription]); 
    DuringAudioPrep = false; 
    return; 
} 
[self lock]; 
[self setAudioPlayer: player]; 
[self ActivateAudioFunction]; 
[self unlock]; 

}

- (void) setAudioPlayer : (AVAudioPlayer *) player { 
if (Player) 
{ 
    if ([Player isPlaying] || Repeat) // The indication was off??? 
     [Player stop]; 
    [Player release]; 
} 
Player = player; 

}

- (void) ActivateAudioFunction { 
[Player setVolume: Volume]; 
[Player setNumberOfLoops: Repeat];  
[Player play]; 

DuringAudioPrep = false; 

}

Trả lời

0

Mã của bạn có vẻ ổn với tôi như tôi đã thấy, vì vậy có thể có mã ở nơi khác đang gây ra sự cố.

Tôi sẽ nói rằng bạn đang sử dụng một loại thành ngữ kỳ quặc. Thay vì giữ lại trên tạo và phát hành trên bộ, tôi muốn làm một cái gì đó như thế này:

// new players will always be created autoreleased. 
    AVAudioPlayer *player = [[(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error] autorelease]; 

- (void) setAudioPlayer : (AVAudioPlayer *) player 
{ 
    if (Player) 
    { 
     if ([Player isPlaying] || Repeat) // The indication was off??? 
      [Player stop]; 
     [Player release]; 
    } 
    Player = [player retain]; 
} 

Bằng cách này, bạn chỉ giữ lại "chơi" các đối tượng khi họ thực sự đi vào phương pháp setAudioPlayer của bạn, mà có thể làm cho nó dễ dàng hơn để theo dõi.

Ngoài ra, hãy xác minh rằng đó thực sự là đối tượng AVAudioPlayer bị rò rỉ. Dụng cụ sẽ có thể xác minh điều này cho bạn.

+0

Cảm ơn câu trả lời. Có - Tôi đã xác minh rằng đó là AVAudioPlayer with Instruments. Theo phương pháp - tôi sử dụng phương pháp này vì tôi thực sự lưu các bản nhạc khác nhau và sử dụng lại chúng bằng cách khớp tên và nếu chúng không phát (thay vì tải xuống cùng một bản nhiều lần). Vì tôi biết rằng tôi nhận được Người chơi từ người gọi sau khi thực hiện 'Alloc' trên nó, tôi biết rằng nó đã được giữ lại (trừ khi tôi đã sai?) – Adi

7

Đây là phương pháp tạo AVAudioPlayer mà không gây rò rỉ bộ nhớ. See this page for explaination.

Tôi đã xác nhận trong ứng dụng của mình rằng điều này đã xóa AVAudioPlayer của tôi bị rò rỉ 100%.

- (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *)path { 
    NSData *audioData = [NSData dataWithContentsOfFile:path]; 
    AVAudioPlayer *player = [AVAudioPlayer alloc]; 
    if([player initWithData:audioData error:NULL]) { 
     [player autorelease]; 
    } else { 
     [player release]; 
     player = nil; 
    } 
    return player; 
} 
+1

Tôi nghĩ rằng nó nên được gõ NSData * audioData vào thứ hai dòng ... – SpaceDog

+0

Mã này thực sự là kỳ lạ, không có lý do gì để tách ra các cuộc gọi cấp phát so với init. Để có cách tiếp cận tổng quát tốt hơn, hãy xem http://stackoverflow.com/questions/17603551/arc-forbids-autorelease/17604365#17604365 hoặc bạn chỉ có thể thêm tự động phát như trong [[[AVAudioPlayer alloc] initWithData: audioData error: NULL] autorelease ] – MoDJ

-2

Hãy thử thêm MediaPlayer.framework cho dự án

+0

'MediaPlayer.framework'? 'AVAudioPlayer' nằm trong' AVFoundation.framework' và không nên yêu cầu 'MediaPlayer'. Chăm sóc để xây dựng? –

2

của bạn Thực hiện AVAudioPlayerDelegate giao thức và phương pháp audioPlayerDidFinishPlaying của nó: thành công: sau đó nhả cầu thủ đối tượng âm thanh

ví dụ.

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { 
    [player release]; // releases the player object 
}