My appには、RemoteIO AudioUnitフレームワークから呼び出される音声録音コールバックがあります。 AudioUnitはメインスレッドとは別のスレッドでコールバックを呼び出します。したがって、オートリリースプールはありません。このコールバックでは、私は以下を行います:音声コールバックスレッド(iOS)のメモリリーク
- 記録されたサンプルのバッファを割り当てます。
AudioUnitRender
を呼び出してこのバッファをいっぱいにします。freopen
を使用してログファイルを開きます。- オーディオ処理メソッドを呼び出します。
- オーディオに応じて、
performSelectorOnMainThread
(ビューコントローラに送信)を使用してメインスレッドのUIを更新します。
はまた、私はオーディオコールバックが初めて呼び出され、したがって前に、オーディオセッションが初期化される前に、私はビューコントローラのviewDidLoad
に呼び出すいくつかのベンチマークを行いtestFilter()
と呼ばれる機能を持っています。この関数では、バッファ(malloc/freeを使用して)を割り当て、前述の同じオーディオ処理メソッドを呼び出します。
さて、問題は(デバイスではなく、シミュレータ上で)です:
- 私は
testFilter()
への呼び出しをコメントアウトした場合、私は任意のメモリ・リーク関連のメッセージを得ることはありません。
2011-01-20 23:
私は testFilter()
を呼ぶならば、私はオーディオコールバック内からのメッセージの束を取得を開始(最初の5つのメッセージはtestFilter()
方法から私のログがあります): 05:10.358計時[389:307]バッファを初期化...2011-01-20 23:05:10.693計時[389:307] ...
2011-01-20 23時05分に行わ:10.696 TimeKeeper [389:307]処理バッファー...
2011-01-20 23:05:15.772計時[389:307]に行わ...
2011-01-20 23:05:15.775計時[389:307]の経過時間5.073843
2011-01-20 23:05:16.319計時[389:660F] * __NSAutoreleaseNoPool():クラス__NSCFDataのオブジェクト0x137330が適所にないプールで自動解放 - ちょうど
2011-01-20 23:05をリーク。 16.327 TimeKeeper [389:660f] * __NSAutoreleaseNoPool():__NSCFDataクラスのオブジェクト0x1373a0は、プールなしで自動リリース - ちょうどリークしています
などとなる。コールバックには、ログに表示されているように、別のスレッドがあります。
オーディオセッションが初期化される前に呼び出され、終了した関数を呼び出すと、これらの警告はどうして起こりますか?どのようにして漏れを検出できますか?
付録
関連するメソッド:
void testFilter() {
#if TARGET_IPHONE_SIMULATOR == 0
freopen([@"/tmp/console.log" cStringUsingEncoding:NSASCIIStringEncoding],"a",stderr);
#endif
int bufSize = 2048;
int numsec=100;
OnsetDetector * onsetDetector = [[OnsetDetector alloc] init];
AudioSampleDataType *buffer = (AudioSampleDataType*) malloc (44100*numsec * sizeof(AudioSampleDataType)); // numsec seconds of audio @44100
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mData = buffer;
bufferList.mBuffers[0].mDataByteSize = sizeof (AudioSampleDataType) * bufSize;
bufferList.mBuffers[0].mNumberChannels = 1;
//--- init buffer
NSLog(@"\n\n---***---***---");
NSLog(@"initializing buffer...");
for (int i = 0; i < 44100*numsec; ++i) {
*(buffer+i) = (AudioSampleDataType)rand();
}
NSLog(@"done...");
NSLog(@"processing buffer...");
CFAbsoluteTime t0 = CFAbsoluteTimeGetCurrent();
for (int i = 0; (i+1)*bufSize < 44100*numsec; ++i) {
bufferList.mBuffers[0].mData = buffer + i * bufSize;
[onsetDetector process:&bufferList];
}
CFAbsoluteTime t1 = CFAbsoluteTimeGetCurrent();
NSLog(@"done...");
NSLog(@"elapsed time %1.6f",(double)(t1-t0));
free(buffer);
[onsetDetector release];
}
そして:
OSStatus recordingCallback (void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
AudioBufferList bufferList;
// redundant
SInt16 *buffer = (SInt16 *)malloc (sizeof (AudioSampleDataType) * inNumberFrames);
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mData = buffer;
bufferList.mBuffers[0].mDataByteSize = sizeof (AudioSampleDataType) * inNumberFrames;
bufferList.mBuffers[0].mNumberChannels = 1;
ioData = &bufferList;
// Obtain recorded samples
OSStatus status;
MainViewController *mainViewController = (MainViewController *)inRefCon;
AudioManager *audioManager = [mainViewController audioManager];
SampleManager *sampleManager = [audioManager sampleManager];
status = AudioUnitRender([audioManager audioUnit],
ioActionFlags,
inTimeStamp,
inBusNumber, //1
inNumberFrames,
ioData);
#if TARGET_IPHONE_SIMULATOR == 0
freopen([@"/tmp/console.log" cStringUsingEncoding:NSASCIIStringEncoding],"a",stdout);
#endif
// send to onset detector
SInt32 onset = [[audioManager onsetDetector] process:ioData];
if (onset > 0) {
NSLog(@"onset - %ld\n", sampleManager.recCnt + onset);
//--- updating the UI - must be done on main thread
[mainViewController performSelectorOnMainThread:@selector(tapButtonPressed) withObject:nil waitUntilDone:NO];
[mainViewController performSelectorOnMainThread:@selector(onsetLedOn) withObject:nil waitUntilDone:NO];
}
sampleManager.recCnt += inNumberFrames;
free(buffer);
return noErr;
}
この頭痛の最終的な結論は、 'freopen'と' NSLog'をまったく使っていないのですが、ファイル出力(Cの 'fprintf'やいくつかのCocoaファイルIOクラス) –