2010-07-08 6 views
4

최종 업데이트 :이 문제에 대한 수정 사항은 우울합니다. 프로젝트 내의 .xcodeproj 디렉토리로 이동하여 <username>.mode1v3<username>.pbxuser 파일을 제거하십시오. 그것은 그것을 고쳤다. 부, Xcode.내 프로그램 objc_msgSend() 동안 _class_isInitialized() EXC_BAD_ACCESS받는 이유는 무엇입니까?


일반적인 유지/릴리스 버그가 아닙니다. 방금 내 코드의 개발 브랜치에서 시작되었지만, 버그는 마스터 브랜치에 존재하지 않으며, 응답에서 소스를 가리키는 차이점을 찾는 데 어려움을 겪고 있습니다. 그래서 나는 단지 피곤한 물건에 도착할 것이다.

보기 컨트롤러 클래스가 있습니다. 두 개의 다른 뷰 컨트롤러를 참조하는 두 개의 속성이 있습니다. 필요에 따라 각과 같이, 게터 접근을 통해로드 :

나중에 전화 [self notesViewController]에, 모든 좋은
- (NotesViewController *)notesViewController { 
    if (notesViewController == nil) { 
     notesViewController = [[NotesViewController alloc] initWithNibName:@"NotesViewController" bundle:nil]; 
    } 
    return notesViewController; 
} 

. 하지만 아마도 그 전에 분명히 펜촉로드하는 동안, 그것을 밖으로 폭탄,

- (DateFieldController *)dateFieldController { 
    NSLog(@"made it into the method at least ..."); 
    if (dateFieldController == nil) { 
     NSLog(@"nib loader, don't let us down..."); 
     dateFieldController = [[DateFieldController alloc] initWithNibName:@"DateFieldController" bundle:nil]; 
    } 
    return dateFieldController; 
} 

이 방법은 다른 접근과 같은 방식으로 호출되는 경우 :

2010-07-08 11:44:58.029 MyApp[24404:207] made it into the method at least ... 
2010-07-08 11:44:58.030 MyApp[24404:207] nib loader, don't let us down... 
Program received signal: “EXC_BAD_ACCESS”. 
(gdb) bt 
#0 0x028bb0ca in _class_isInitialized() 
#1 0x028b9eca in _class_initialize() 
#2 0x028bf1f6 in prepareForMethodLookup() 
#3 0x028b86c9 in lookUpMethod() 
#4 0x028b8836 in _class_lookupMethodAndLoadCache() 
#5 0x028c6ad3 in objc_msgSend() 
#6 0x00007bb3 in -[EntryViewController controllerForFieldType:] (self=0x7942d70, _cmd=0x190c20, type=0x79844b0) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/Classes/EntryViewController.m:481 
#7 0x00007e07 in -[EntryViewController selectTypesControllerDidSelect:] (self=0x7942d70, _cmd=0x190bb4, type=0x79844b0) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/Classes/EntryViewController.m:527 
#8 0x0000d2ad in -[TypesViewController tableView:didSelectRowAtIndexPath:] (self=0x5d2aac0, _cmd=0x1eac458, aTableView=0x6056000, indexPath=0x781c780) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/Classes/TypesViewController.m:81 
#9 0x0059e718 in -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:]() 
#10 0x00594ffe in -[UITableView _userSelectRowAtIndexPath:]() 
#11 0x002abcea in __NSFireDelayedPerform() 
#12 0x0274cd43 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__() 
#13 0x0274e384 in __CFRunLoopDoTimer() 
#14 0x026aad09 in __CFRunLoopRun() 
#15 0x026aa280 in CFRunLoopRunSpecific() 
#16 0x026aa1a1 in CFRunLoopRunInMode() 
#17 0x02fd02c8 in GSEventRunModal() 
#18 0x02fd038d in GSEventRun() 
#19 0x0053ab58 in UIApplicationMain() 
#20 0x00001e24 in main (argc=1, argv=0xbffff050) at /Users/wgray/Documents/Sources/iPhone/MyApp-iphone/main.m:14 
(gdb) 
이 사람은, 그러나, 단지 작동이 중지

nib로드 메소드를 실행할 때 Simulator SDK에서 이상한 일이 발생하는 것으로 보입니다. 사실, 어쩌면 더 일찍. 오버 타고 DateFieldController에 약간의 NSLog 액션으로 펜촉 로딩 초기화하는 것은 의심데도 우리를 얻을 수 없습니다 :

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
    NSLog(@"come on, you..."); 
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) 
    { 
    NSLog(@"rock on!"); 
    } 
    return self; 
} 

충분 말을,이 NSLog 문 중 어느 것도 지금까지 실행됩니다.

무슨 일 이니? 왜 런타임이 나에게 날아 오르는거야? (self.dateFieldController에서 [self dateFieldController]으로 전화를 전환해도 버그가 수정되지 않으며,이 코드는 충돌이없는 마스터 분기의 코드와 정확히 동일 함을 기억하십시오.

FWIW, 시뮬레이터 4.0, 디버그, i386 아치 (OS X 10.6.3을 실행하는 새로운 Mac Book Pro)에서 컴파일하는 Xcode 3.2.3 64 비트를 사용하여 구축 중이며 프로젝트 설정의 배포 대상이 설정됩니다. "iPhone OS 3.0"(uppping to this 3.1.3) 역시이 문제를 해결하지 못합니다. 요청에 따라는 controllerForFieldType:의 구현 :

는 업데이트 나는 그것이 특히 관련이 있다고 생각하지 않기 때문에 나는 초를 남겨

- (id)controllerForFieldType:(Type *)type { 
    id controller = nil; 

    if ([type.mode isEqualToString:@"note"]) { 
     controller = self.notesViewController; 
    } else if ([type.mode isEqualToString:@"date"]) { 
     NSLog(@"going for it, attempting to load dateFieldController from accessor..."); 
     controller = self.dateFieldController; 
    } else { 
     controller = self.fieldViewController; 
    } 

    return controller; 
} 

는 문제에서, 스택 이후에 일어나고있는 것 같다 실제의 getter 메소드 dateFieldController

업데이트 II : @ zneak의 제안에 따라 Run -> Enable Guard Malloc 설정을 사용하고 시나리오를 다시 실행했습니다. 결과는 기본적으로 동일하지만 런타임의 내부 백 트레이스가 다릅니다. 무언가가 디코딩되는 것을 방지 년대 클래스 또는 NIB 잘못 것으로 생각된다 :

2010-07-08 12:26:26.180 Strip[24961:207] made it into the method at least ... 
2010-07-08 12:26:26.289 Strip[24961:207] nib loader, don't let us down... 
Program received signal: “EXC_BAD_ACCESS”. 
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Not safe to call dlopen at this time.) 
(gdb) bt 
#0 0x028cd41f in attachMethodLists() 
#1 0x028cdf77 in realizeClass() 
#2 0x028cedad in _class_getNonMetaClass() 
#3 0x028c8eb0 in _class_initialize() 
#4 0x028ce1f6 in prepareForMethodLookup() 
#5 0x028c76c9 in lookUpMethod() 
#6 0x028c7836 in _class_lookupMethodAndLoadCache() 
#7 0x028d5ad3 in objc_msgSend() 
#8 0x00007b81 in -[EntryViewController controllerForFieldType:] (self=0x38cfaf30, _cmd=0x190c8f, type=0x3cacbfe0) at /Users/wgray/Documents/Sources/iPhone/strip-iphone/Classes/EntryViewController.m:482 
...snip... 
#22 0x00001de4 in main (argc=1, argv=0xbfffefec) at /Users/wgray/Documents/Sources/iPhone/strip-iphone/main.m:14 
(gdb) 

업데이트 III를 : 음모가 두껍게하는.의견에서 @ ohorob의 제안에 따라 env arg OBJC_PRINT_INITIALIZE_METHODS = YES를 추가하여 여기에있는 하나의 클래스를 제외한 앱의 모든 단일 클래스 초기화가 잘 보이는 것으로 나타났습니다. 나는 응용 프로그램을 실행하고 폭발에 이르게 테이블 행을 선택하면

objc[26750]: INITIALIZE: calling +[UIPinchGestureRecognizer initialize] 
objc[26750]: INITIALIZE: finished +[UIPinchGestureRecognizer initialize] 
objc[26750]: INITIALIZE: UIPinchGestureRecognizer is fully +initialized 

, 우리는 단지 충돌하기 전에 nslog 콘솔 출력을보고, 충돌 자체 : 각 콘솔 출력이 같은 대한 보인다. 나는 이것이 부적절한 초기화를 배제 할 수 있다는 것을 의미한다고 생각하고 싶다. 그러나 나는 런타임에 대한 전문가가 아니다.

master 브랜치와이 dev 브랜치 간의 코드 차이에 대한 철저한 감사를했는데, 아직 포인터를 밟았 음을 나타내는 아무것도 발견되지 않았지만, 나는 그것이 대부분 계속 될 것이라고 생각하고 있습니다.

+0

또한 [[EntryViewController controllerForFieldType :]'의 코드를 게시하십시오 ... –

+0

우리는 위에서 보았던 로그 메시지를 고려할 때 아마도 무의미하다고 생각합니다. –

+0

'dateFieldController'가 스택 추적에 나타나지 않고 코드가 작동중인 버전에서 변경되지 않았다면 문제가 실제로 다른 곳인지 의심 할 수 없습니다. 예 :'controllerForFieldType'은 어떻게 생겼습니까? – walkytalky

답변

1

문제가 계속 발생한다는 사실은 내가 런타임의 내부 클래스 데이터 구조. 내가 제일 먼저 의심하는 점은 지나치게 영리한 수업이 될 것입니다. 너와 함께 게임을하는 수업이 없니? 이에 대한 예는 XMPPMessage.m을 참조하십시오. 이보기 컨트롤러 클래스가 isa와 함께 작동하는지 묻지 않습니다. 나는 틀린 짓을하기 때문에 시스템에있는 모든 클래스가 뜻밖의 방식으로 메모리를 밟을 수 있다는 것을 의미합니다.

다음으로 class_copyMethodList()을 사용하고 + alloc을 호출하기 전에 충돌하는지 확인하십시오. 그렇다면 클래스 테이블이 확실히 손상되었습니다.

+0

나는 당신의 대답에 겁 먹었지 만, 나는 그것에 대해 조사 할 것입니다! 감사. P. 나는 그것이 정말로 움직이고 있는지 확신하지 못한다. 런타임에서 다른 메소드 호출을 강제로 사용하는 "Enable Guard Malloc"을 사용하지 않는 한 백 트레이스는 매번 동일하다. –

+0

그래, 난 아무것도에 isa 속성을 망치고있어. DateFieldController는 NotesFieldController와 마찬가지로 DataFieldController의 하위 항목입니다. 하나는로드되고 다른 폴드는로드됩니다. DataFieldController는 단순히 UIViewController의 하위 클래스입니다. 그래서 재밌는 사업은 아니라고 생각합니다. 어떻게 "class_copyMethodList()"를 사용하고 계신지, 그냥 들어가십시오. –

+0

나는 다음과 같은 것을 테스트한다. "unsigned count; Method * methods = class_copyMethodList ([NotesViewController class], & count);" + alloc을 호출하고 충돌이 발생했는지 확인하십시오. #import 가 필요합니다. 문제가 해결되면 다른 곳에서도 문제가 발생할 수 있지만 충돌이 발생하면 내부 테이블이 밟히게 될 가능성이 큽니다. –

2

클래스 초기화 중에 뭔가 이상한 일이 있습니다.

OBJC_PRINT_INITIALIZE_METHODS 환경 변수를 YES로 설정하고 응용 프로그램을 실행 해보십시오. 그것은 우리에게 단서를 줄 수 있습니다. 아니. (Xcode의 실행 가능 인스펙터에서 환경 변수를 설정하십시오 - the docs 참조).

+initialize 방법이 있습니까? (모든 클래스에서 - 클래스 중 하나가 충돌과 관련없는 것으로 보이는 초기화를 간지럽니다.)

+0

EntryViewController 또는 DateFieldController에 + initialize 메소드가 없습니다. –

+0

아니, 아니 + 초기화하십시오.// .bash_login에서 env var을 설정하는 곳/방법은 무엇입니까? 또는 빌드 설정 중 하나에서 ... –

+0

Xcode에서 현재 실행 파일 정보를 확인하십시오. "인수"탭의 아래쪽 창에서 변수를 설정하십시오. – ohhorob

관련 문제