2011-12-05 11 views
0

開発中のアプリでフリーズの問題を追跡しようとしています。私はNSAutoreleasePoolの深いところにいるかもしれないし、物事をねじっています。NSAutoreleasePoolを使用してフリーズする

アプリはmidiファイルを再生しています。 NSAutoreleasePoolを使用する「simRespondToFileNote」コードをコメントアウトすると、フリーズしません。私はコードを実行させると、それは一見無作為なポイントでフリーズします。クラッシュログ/コンソール出力は、問題の発生場所を示さないようです。ここで

は、プログラムの流れです:

  1. 私は低音ミディLIB(C libに)を使用しています。それは独自のスレッドでMIDIファイルを再生します。

  2. midiイベントが発生すると、コールバックがトリガされ、NSDictionaryでMIDIイベントデータをラップし、メインスレッドにルーティングして、UIの更新やその他の処理を実行できます。メッセージはPARAMとしてNSDictionaryのインスタンスを使用して別のオブジェクトに送られるデリゲートから

    - (void)forwardFileNoteIn:(int) note withVelocity: (int) velocity 
    { 
    int position = BASS_ChannelGetPosition(midiFileStream, BASS_POS_MIDI_TICK); 
    float percent = ((float)position/(float)totalTicks); 
    int ticksInLoop = outLoopTick - inLoopTick; 
    
    QWORD bytes=BASS_ChannelGetPosition(midiFileStream, BASS_POS_BYTE); // get position in bytes 
    double seconds=BASS_ChannelBytes2Seconds(midiFileStream, bytes); // translate to seconds 
    int timeStamp =seconds*1000; // translate to milliseconds 
    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSDictionary *midiData = [NSDictionary dictionaryWithObjectsAndKeys: 
              @"fileNoteIn", @"eventType", 
              [NSNumber numberWithInt:note], @"note", 
              [NSNumber numberWithInt:velocity],@"velocity", 
              [NSNumber numberWithInt:timeStamp],@"timeStamp", 
              [NSNumber numberWithInt:position],@"position", 
              [NSNumber numberWithFloat:percent],@"percentPlayed", 
              [NSNumber numberWithInt:ticksInLoop],@"ticksInLoop", 
              nil]; 
    
    [delegate performSelectorOnMainThread:@selector(midiFileEvent:) 
              withObject:midiData 
              waitUntilDone:NO]; 
    [pool release]; 
    

    }

    1. :ここ

    ルーティングを行うコードです。そのオブジェクトは、すぐに別のオブジェクトにNSDictionaryインスタンスを送信するか、または短い遅延の後に送信するようにキューに入れます(performSelector:afterDelay:を使用)。

キューに入れられたメッセージがトリガーされる前にNSAutoreleasePoolがNSDictionaryインスタンスを削除している可能性はありますか?私はプールをどこにでも排水していません - 私はそれをしなければいけませんか?

- (void)simRespondToFileNote:(NSDictionary *)dictionary 
{ 
int velocity = [[dictionary objectForKey:@"velocity"] intValue]; 

if (velocity == 0){ 
    // noteOff - send it through 
    [delegate routeUserSimMidiEvent:dictionary]; 
} else { 

    float totalPercentCorrect = [dataSource getUserCorrectPercent]; 

    int note = [[dictionary objectForKey:@"note"] intValue]; 

    if (totalPercentCorrect < _userAccuracy){ 

     float lateNoteOnTimeDelay = (dataSource.postTimeHighAccuracy - (dataSource.postTimeHighAccuracy /4))/1000.; 
     float lateNoteOffTimeDelay = lateNoteOnTimeDelay + .1; // revise 

     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

     // create noteOff data w/ velocity == 0; timeStamp == 0; 
     NSDictionary *midiData = [NSDictionary dictionaryWithObjectsAndKeys: 
            [NSNumber numberWithInt:note], @"note", 
            [NSNumber numberWithInt:0],@"velocity", 
            [NSNumber numberWithUnsignedInt:0],@"timeStamp", 
            nil]; 

     [self performSelector:@selector(simLateResponseToFileNote:) withObject:dictionary afterDelay: lateNoteOnTimeDelay]; 
     [self performSelector:@selector(simLateResponseToFileNote:) withObject:midiData afterDelay: lateNoteOffTimeDelay]; 
     [pool release]; 

    } else { 

     float lateNoteOnTimeDelay = (dataSource.postTimeLowAccuracy + (dataSource.postTimeLowAccuracy /4))/1000.0; 
     float lateNoteOffTimeDelay = lateNoteOnTimeDelay + .1; // revise 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

     // create noteOff data w/ velocity == 0; timeStamp == 0; 
     NSDictionary *midiData =[NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithInt:note], @"note", 
           [NSNumber numberWithInt:0],@"velocity", 
           nil]; 

     // queue late noteOn 
     [self performSelector:@selector(simLateResponseToFileNote:) withObject:dictionary afterDelay: lateNoteOnTimeDelay]; 
     // queue late noteOff 
     [self performSelector:@selector(simLateResponseToFileNote:) withObject:midiData afterDelay: lateNoteOffTimeDelay]; 
     [pool release]; 

    } 
} 

}

答えて

1

simRespondToFileNote:の一時的な自動解放プールのあなたの作成は非常に便利ではありませんが、問題になることはありません。 performSelector:withObject:afterDelay:へのあなたのコールは、呼び出されるまでdictionaryを保持します。 forwardFileNoteIn:withVelocity:がまだ自動解放プールを持たないスレッド上にある場合、作成する必要があるかもしれませんが、一般的にはメソッドの最上部で行います。このスレッドにすでにプールがある場合、ここに作成する理由はありません。

あなたの説明から、simLateResponseToFileNote:がメインスレッドを長時間ブロックしていると思われます。私はボトルネックのためにそこを見るだろう。

+0

私は 'simRespondToFileNote:'でautoreleaseプールを取り出し、それがどのように冗長であるかを理解しています。まだ凍っている。私は(正しい用語をここでは知らない)原因が大きすぎるスタック(?)を元の辞書( 'forwardFileNoteIn:'から)を再利用することによって、複数のメソッド呼び出しを介してargとして渡します。 –

+0

辞書を渡すのは非常に安いです。 ObjCはヒープ上のすべてのオブジェクトを割り当て、ポインタのみを渡します。だから、それは辞書の通過ではありません。私はInstrumentsを介してこれを実行し、ハングアップ中にCPUに何がぶつかっているのかを確認します。ありがとう。 –

+0

ありがとう。辞書は、高価なアプローチではないことを喜んで行きました。特定の辞書がどれくらいのメモリを使用しているかを判断する方法はありますか?辞書のオーバーヘッド?インストゥルメント、メモリ、割り当て、ゾンビなどでプロジェクトを実行しました。問題と思われるリークや問題は表示されません(問題を構成するものがわからない可能性があります); –

1

あなたは、プールを排出、パラメータとしてmidiDataを使用して遅れperformSelectorをやって、自動解放プールにあなたのmidiDataオブジェクトを作成しています。ここに問題がないのですか?

(自動解放プールを解放すると、それを排出することと同じです。(マニュアルを参照してください。))

+1

'performSelector'は、渡されたオブジェクトと受信者を保持します。ありがとう。 –

+0

はい、私は今それを取得します。ありがとう。 –

関連する問題