1

私はiPhoneアプリを作成中ですが、メモリにいくつか問題があります。以下のコードは次のとおりです。

NSURL *url = [curItem valueForProperty: MPMediaItemPropertyAssetURL];

AVURLAsset *asset = [AVURLAsset URLAssetWithURL: url options:nil];

NSError *error = nil;

AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:asset error:&error];

AVAssetTrack* track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

NSMutableDictionary* audioReadSettings = [NSMutableDictionary dictionary];
[audioReadSettings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM]
                     forKey:AVFormatIDKey];

AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:audioReadSettings];

[reader addOutput:readerOutput];

[reader startReading];

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

while( sample != NULL)
{
    sample = [readerOutput copyNextSampleBuffer];

}
CFRelease(sample);

ユーザーのiTunesライブラリから曲を読んでいます(curItemは現在の曲です)。最後の行を残すとCFRelease(sample)、コードでプログラムが停止します(エラーは表示されません)。クラッシュするだけです。この行をコメントアウトすると、もちろんメモリの問題が発生し、「Receivedmemorywarning」を受け取った後の4曲目あたりでコードがクラッシュします。

私は何が間違っているのですか?

4

2 に答える 2

1

命名規則copyNextSampleBufferは、返されたオブジェクトを所有しているため、それを解放するのは正しいことを意味しますが、copyNextSampleBufferメソッドをループ内で複数回呼び出し、解放せずに前のコピーを上書きしています。

最終的にCFReleaseを呼び出すときは、NULLであるとチェックしたばかりの変数でそれを呼び出しています。このStackOverflowの回答によると、NULLでCFReleaseを呼び出すことは安全ではないため、クラッシュしているのはそのためです。

代わりに行う必要があるのは、次のように、変数を上書きする前に、whileループ内でreleaseを呼び出すことです。

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

while( sample != NULL)
{
    CFRelease(sample);
    sample = [readerOutput copyNextSampleBuffer];
}

それでもクラッシュが修正されない場合(および修正された場合でも)、コードに対して静的アナライザーを実行してみて(Xcodeの製品メニューで[分析]を選択)、潜在的なリークまたはオーバーリリースが報告されるかどうかを確認してください。黄色と青色の警告はすべてクラッシュの可能性があるため、すべて修正してみてください。

編集:あなたのループがあまり意味をなさないことが私には思い浮かびます-なぜあなたはサンプルを何度も読んでからそれらを捨てるのですか?whileループでNULLチェックが間違っていたので、実際には代わりにこれを書くつもりでしたか?

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

while( sample == NULL)
{
    sample = [readerOutput copyNextSampleBuffer];
}

CFRelease(sample);

その場合、サンプルをリリースする前にサンプルがNULLでないことを明示的にチェックしているので、これも問題ありません。ただし、サンプルを使用する前にサンプルを破棄しているため、readerOutputにサンプルが含まれていない場合は、無限ループが発生する可能性があります。

于 2012-01-06T00:35:16.950 に答える
0

自動リリースまたはARCのいずれかを使用して、「早すぎるリリースシンドローム」を取り除きます。どちらの場合も、リリースタスクは他の誰かによって管理されています。新しいプロジェクトについては、ARCをお勧めします。

于 2012-01-04T19:44:29.453 に答える