我試圖追蹤我正在開發的應用程序的凍結問題。我可能會在NSAutoreleasePool的最後端,並搞砸了。使用NSAutoreleasePool凍結
該應用正在播放MIDI文件。如果我註釋掉下面使用NSAutoreleasePool的代碼「simRespondToFileNote」,它不會凍結。如果我讓代碼運行,它將凍結在看起來隨機的點崩潰日誌/控制檯輸出似乎並沒有表明問題發生的地方。
下面是程序流:
我使用的低音MIDI LIB(C LIB);它在它自己的線程中播放MIDI文件。
當發生MIDI事件時,會觸發回調,並將MIDI事件數據包裝在NSDictionary中並將其路由到主線程,以便我可以執行UI更新和其他一些內容。
下面是確實的路由的代碼:
- (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];
}
- 從消息發送到使用所述的NSDictionary實例作爲PARAM另一個對象委託。該對象要麼將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];
}
}
}
謝謝。我在'simRespondToFileNote:'中取出了autorelease池,現在明白這是多餘的。儘管如此,仍然凍結。我想知道如果我造成(不知道這裏的正確術語)太大的堆棧(?)通過重用原始詞典(來自'forwardFileNoteIn:'),因爲我通過多個方法調用將它作爲參數傳遞。 –
傳遞字典非常便宜。 ObjC分配堆上的所有對象,只傳遞指針。所以這不是字典的傳遞。我會通過儀器運行這個程序,看看掛起過程中碰到什麼CPU。 –
謝謝。字典似乎走的路 - 很高興它不是一個昂貴的方法。有沒有一種方法可以確定一個特定的字典使用多少內存: - 像加入條目的內存使用加上?字典開銷?我通過儀器 - 內存,分配,殭屍等運行我的項目。我沒有看到任何泄漏或問題,似乎是一個問題(我可能不知道什麼構成問題.. ;-) –