2013-05-10 3 views
0

저는이 문제에 직면 해 있으며 메모리 관리에 대한 기본 개념이 부족하다는 것을 인정합니다. 나는 이것을 해결할 수 없었고 나를 믿을 수 없었다. 나는 많은 것을 시도해왔다.__NSCFString appendString : NSMutableString for Cocoa에 대한 오류

내 응용 프로그램에는 RS232 포트에서 읽을 4 개의 스레드가 있습니다 (나중에 최대 12 개의 스레드가 될 수 있음). 각 스레드 (threadRS232Read)에서 appendString을 사용하여 NSMutableString에 RS232 문자를 추가합니다. NSMutableString은 전체 테스트가 완료 될 때까지 appendString을 사용하여 엄청나게 커지게됩니다. 그리고 주기적으로 테스트 내에서 clearRdBuffStr이 호출되어 문자열을 지 웁니다. 앱은 항상 appendString에서 충돌합니다. 운이 좋으면 몇 가지 테스트를 실행할 수 있지만 일반적으로 첫 번째 실행에서는 충돌이 발생합니다. 아래 코드 스 니펫과 충돌 로그가 있습니다. 다른 파일 RS232RW.m에서

AppController.h 
... 
`@interface AppController : NSObject { 
... 
NSMutableString *buffStr1, *buffStr2, *buffStr3, *buffStr4; 
...} 

AppController.m 
... 
//in -(id)init 
buffStr1 = [[NSMutableString alloc] initWithString:@""]; 
buffStr2 = [[NSMutableString alloc] initWithString:@""]; 
buffStr3 = [[NSMutableString alloc] initWithString:@""]; 
buffStr4 = [[NSMutableString alloc] initWithString:@""]; 
... 
// in -(void)dealloc 
[buffStr1 release]; 
[buffStr2 release]; 
[buffStr3 release]; 
[buffStr4 release];` 

는 스레드 4

RS232RW.m 
- (void)threadRS232Read:(id)argument { 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
.... 
//read from RS232 port buffer and etc... 
NSString *buffStr = [NSString stringWithUTF8String:buff]; 
    switch (portNo) { 
     case 0: 
      if (buffStr != nil) 
      { 
       [buffStr1 appendString:buffStr]; 
      } 

      break; 
     case 1: 
      if (buffStr != nil) 
      { 
       [buffStr2 appendString:buffStr]; 
      } 
      break; 
     case 2: 
      if (buffStr != nil) 
      { 
       [buffStr3 appendString:buffStr]; 
      } 

      break; 
     case 3: 
      if (buffStr != nil) 
      { 
       [buffStr4 appendString:buffStr]; 
      } 
      break; 
     case 4: 
      if (buffStr != nil) 
      { 
       [buffStr5 appendString:buffStr]; 
      } 
      break; 

     .... 

// clearRdBuffStr will be called by the other part of the program to clear this buffer. 
-(void) clearRdBuffStr:(int) portNo { 
switch (portNo) { 
    case 0: 
     [buffStr1 setString:@""]; 
     break; 
    case 1: 
     [buffStr2 setString:@""]; 
     break; 
    case 2: 
     [buffStr3 setString:@""]; 
     break; 
    case 3: 
     [buffStr4 setString:@""]; 
     break; 
    .... 

앱이 항상 위의 appendString의 1에 충돌에 buffStr1를 업데이트하는 데 사용됩니다.

충돌 로그는 다음과 같습니다 : 같은 인 NSMutableString 같은

.... 


Crashed Thread: 3 

Exception Type: EXC_CRASH (SIGABRT) 
Exception Codes: 0x0000000000000000, 0x0000000000000000 

Application Specific Information: 
objc[584]: garbage collection is OFF 
*** error for object 0x6d02b600: double free 
.... 
Thread 3 Crashed: 
0 libsystem_kernel.dylib   0x905819c6 __pthread_kill + 10 
1 libsystem_c.dylib    0x926ecf78 pthread_kill + 106 
2 libsystem_c.dylib    0x926ddbdd abort + 167 
3 libsystem_c.dylib    0x92701508 szone_error + 333 
4 libsystem_c.dylib    0x92702dd1 free_small_botch + 102 
5 com.apple.CoreFoundation  0x97ee51e8 __CFAllocatorSystemDeallocate + 24 
6 com.apple.CoreFoundation  0x97ee51ba CFAllocatorDeallocate + 266 
7 com.apple.CoreFoundation  0x97ee50a2 __CFStrDeallocateMutableContents + 178 
8 com.apple.CoreFoundation  0x97ee422b __CFStringChangeSizeMultiple + 3147 
9 com.apple.CoreFoundation  0x97f86010 __CFStringCheckAndReplace + 496 
10 com.apple.CoreFoundation  0x97f95dad -[__NSCFString appendString:] + 45 
11 com.TopTestDFU     0x00109f6d -[AppController(RS232RW) 
threadRS232Read:] + 752 
12 com.apple.Foundation   0x92aabf7d -[NSThread main] + 45 
13 com.apple.Foundation   0x92aabf2d __NSThread__main__ + 1582 
14 libsystem_c.dylib    0x926eaed9 _pthread_start + 335 
15 libsystem_c.dylib    0x926ee6de thread_start + 34 
+0

좀비 템플릿이있는 기기에서 앱을 실행하는 것이 좋습니다. 좀비 인 것으로 밝혀지면 (필자는 그렇게 생각하지 않지만 항상 점검할만한 가치가 있습니다.) 인 스트 루먼트는 원인을 찾는데 도움을 줄 것입니다. 만약 좀비가 아니라면, 인스 트루먼 트의 객체 히스토리에서 double-freed 주소를 찾아보고 그것이 무엇인지, 무엇을 생성했는지 등을 볼 수 있습니다. 이것은 필요한 단서 일 수 있습니다. –

답변

0

코코아 변경 가능한 객체가 스레드에 안전하지 않습니다. 어떤 형태의 잠금 장치를 사용하여 동기화를 조정하는 것은 사용자의 몫입니다.

하나의 옵션으로 NSLock을 확인하십시오.

4 개의 NSMutableString을 ivars가 아닌 원자 속성으로 만들 수도 있습니다. 원자는 실제로 스레드 안전을 보장하지 않지만이 경우에는 작동 할 수 있습니다.

[편집] ... 실제로는 각 스레드가 다른 포트 번호를 사용하고 있다면 문제가되는 NSMutableStrings가 아닐 것입니다. 아마 NSString *buffStr = [NSString stringWithUTF8String:buff];이 다른 스레드가 buffStr을 추가하기 전에 하나의 스레드에 의해 호출되고있을 것입니다. 그래서 그 주변에 자물쇠가 있어야합니다.

+0

[Asker가] 답변 해 주셔서 감사합니다. 예. 나는 각 스레드가 다른 포트 번호를 사용하고 있다고 확신한다. 사실 NSMutableString을 속성 (복사 또는 유지)으로 사용하고 NSLock을 사용하려고했지만 이전과 마찬가지로 여전히 충돌합니다. ... '스위치 (PORTNO) { 경우 0 (! 버프 [0] ='\ 0 ') { 는 [lock_buffStr [PORTNO] LOCK] 경우; [buffStr1 appendString : [NSString stringWithUTF8String : buff]]; [lock_buffStr [portNo] unlock]; } 휴식; .... – user2370312