나는 로그 정보를 보유하고 그것을 N 라인마다 파일에 덤프하는 logBuffer라는 NSMutableArray 객체를 가지고있다. 그렇게되면, 내가경계 초과 NSMutableArray removeAllObjects
[logBuffer removeAllObjects]
로, 모든 항목을 제거 때때로 이것은 예외가 발생합니다 : 내가 배열에있는 모든 개체를 통해 removeAllObjects 내부적으로 반복 추측
[__NSArrayM removeObjectAtIndex:]: index 7 beyond bounds [0 .. 6]
을, 그러나 나는 확실하지 않다 방법을 그 한계를 넘어 설 수 있습니다. 내 유일한 생각이지만 개체가 제거되는 동안 배열을 조작하는 다른 스레드가 있지만 전혀 모르겠습니다.
의견이 있으십니까?
편집 :
- (void) addToLog:(NSString*)str {
[logBuffer addObject:s];
if ([logBuffer count] >= kBufferSize) {
[self writeLogOnFile];
}
}
- (void) writeLogOnFile {
NSArray *bufferCopy = [NSArray arrayWithArray:logBuffer]; // create a clone, so that logBuffer doesn't change while dumping data and we have a conflict
NSString *multiline = [bufferCopy componentsJoinedByString:@"\r\n"];
multiline = [NSString stringWithFormat:@"%@\n", multiline];
NSData *data = [multiline dataUsingEncoding:NSUTF8StringEncoding];
NSFileHandle *outputFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
[outputFileHandle seekToEndOfFile];
[outputFileHandle writeData:data];
[outputFileHandle closeFile];
[logBuffer removeAllObjects]; // This is where the exception is thrown
}
[CrashManager addToLog :] 메인 스레드에서 항상 클래스의 수십에 의해 호출되는 몇 가지 추가 코드입니다. 여기
는 역 추적입니다 :
"0 AClockworkBrain 0x0008058f -[SWCrashManager backtrace] + 79",
"1 AClockworkBrain 0x0007fab6 uncaughtExceptionHandler + 310",
"2 CoreFoundation 0x041fe318 __handleUncaughtException + 728",
"3 libobjc.A.dylib 0x03c010b9 _ZL15_objc_terminatev + 86",
"4 libc++abi.dylib 0x044c9a65 _ZL19safe_handler_callerPFvvE + 13",
"5 libc++abi.dylib 0x044c9acd __cxa_bad_typeid + 0",
"6 libc++abi.dylib 0x044cabc2 _ZL23__gxx_exception_cleanup19_Unwind_Reason_CodeP17_Unwind_Exception + 0",
"7 libobjc.A.dylib 0x03c00f89 _ZL26_objc_exception_destructorPv + 0",
"8 CoreFoundation 0x041171c4 -[__NSArrayM removeObjectAtIndex:] + 212",
"9 CoreFoundation 0x04153f70 -[NSMutableArray removeAllObjects] + 96",
"10 AClockworkBrain 0x000817c3 -[SWCrashManager writeLogOnFile] + 691",
"11 AClockworkBrain 0x0008141d -[SWCrashManager addToLog:] + 429",
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM removeObjectAtIndex:]: index 7 beyond bounds [0 .. 6]'
편집 # 2
제안에 대한 @synchronize
을 읽은 후, 나는 그것을 수정 :
- (void) addToLog:(NSString*)str {
[self performSelectorOnMainThread:@selector(doAddToLog:) withObject:str waitUntilDone:YES];
}
- (void) doAddToLog:(NSString*)str {
// Do the real stuff
}
- (void) writeLogOnFile {
[self performSelectorOnMainThread:@selector(doWriteLogOnFile) withObject:nil waitUntilDone:YES];
}
- (void) doWriteLogOnFile {
// Do the real stuff
}
내가 테스트 fe에 대한 코드 w 시간이 걸리며 예외가 발생하지 않았습니다. 그것은 시간당 약 1-2 번 충돌하기 때문에 문제가 해결되었다고 가정합니다. 누군가이 접근법이 @synchronize
제안과 어떻게 다른지 설명 할 수 있습니까?
또한 waitUntilDone : YES를 사용하는 것이 좋을지, 아니면이 경우 NO를 사용하는 것이 더 좋을까요? 당신은 그것을 제공 한
"내 유일한하지만 개체가 제거되는 동안 배열을 조작하는 다른 스레드 있다는 것입니다"- 경쟁 조건 내 순간이었다가 생각뿐. 어떻게 배열을 사용하고 있습니까? –
* removeAllObjects *를 호출하기 바로 전에 배열의 크기를 기록하십시오. 그런 다음 충돌 로그에서 배열의 크기를 읽습니다 (예를 들어, [0..6]은 크기가 7입니다). 크기가 변경되면 * removeAllObjects * 실행 중에 배열을 편집하고있는 것입니다. – rdurand
개체를 반복적으로 제거하고 시도해 볼 수 있습니다. 아마도 무언가를 찾을 수 있습니다. – rdurand