2010-05-31 2 views
0

사용자가 아래에 나열된 스택 추적을 사용하여 충돌 보고서를 보냈습니다 (직접 충돌을 재현하지 못했지만이 사용자가보고 한 다른 모든 충돌은 유효한 버그였습니다. 효과). 이 애플리케이션은 참조 카운트 된 Objective-C/Cocoa 앱입니다.할당 취소 된 개체를 가리키는 NSDrawer 대리자?

올바르게 해석 할 경우 충돌이있는 것은 drawerDidOpen: 메시지를 할당 취소 된 개체로 보내려고 할 때 발생합니다. drawerDidOpen:을 받아야하는 유일한 개체는 서랍의 대리자 개체 (서랍 알림을 받기 위해 개체를 등록하지 않음)이며 서랍의 대리자 개체는 XIB/NIB 파일을 통해 인스턴스화되며 서랍의 대리인 콘센트에 연결됩니다. 다른 곳에서는 참조됩니다.

그렇다면 어떻게 델리게이트가 서랍 통지 전에 dealloc 된 것을 보호 할 수 있습니까? 아니면 교대로 내가 잘못 해석 한 것이 충돌을 일으켰을 수 있습니까?

충돌 로그/스택 추적 :

Exception Type: EXC_BAD_ACCESS (SIGSEGV) 
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000010 
Crashed Thread: 0 Dispatch queue: com.apple.main-thread 

Application Specific Information: 
objc_msgSend() selector name: drawerDidOpen: 

Thread 0 Crashed: Dispatch queue: com.apple.main-thread 
0 libobjc.A.dylib     0x00007fff8272011c objc_msgSend + 40 
1 com.apple.Foundation   0x00007fff87d0786e _nsnote_callback + 167 
2 com.apple.CoreFoundation  0x00007fff831bcaea __CFXNotificationPost + 954 
3 com.apple.CoreFoundation  0x00007fff831a9098 _CFXNotificationPostNotification + 200 
4 com.apple.Foundation   0x00007fff87cfe7d8 -[NSNotificationCenter postNotificationName:object:userInfo:] + 101 
5 com.apple.AppKit    0x00007fff8512e944 _NSDrawerObserverCallBack + 840 
6 com.apple.CoreFoundation  0x00007fff831d40d7 __CFRunLoopDoObservers + 519 
7 com.apple.CoreFoundation  0x00007fff831af8c4 CFRunLoopRunSpecific + 548 
8 com.apple.HIToolbox    0x00007fff839b8ada RunCurrentEventLoopInMode + 333 
9 com.apple.HIToolbox    0x00007fff839b883d ReceiveNextEventCommon + 148 
10 com.apple.HIToolbox    0x00007fff839b8798 BlockUntilNextEventMatchingListInMode + 59 
11 com.apple.AppKit    0x00007fff84de8a2a _DPSNextEvent + 708 
12 com.apple.AppKit    0x00007fff84de8379 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 155 
13 com.apple.AppKit    0x00007fff84dae05b -[NSApplication run] + 395 
14 com.apple.AppKit    0x00007fff84da6d7c NSApplicationMain + 364 
15 (my app's identifier)   0x0000000100001188 start + 52 

편집는 : 명확히하기 위해이 충돌이 수천 번 일이 아니면 수십 거의-동일한 사용 시나리오의 수천. 나는/release/alloc/dealloc/anything-memory-management를 코드 내 어디에서나 유지하지 않는다. 내 코드에 어떤 종류의 서랍 알림을위한 객체도 등록하지 않습니다. 내 코드에는 대리자 객체를 가리키는 변수 (ivars)가 없습니다.

NIB가 언로드되면 (예 : 문서 창을 닫을 때 Cocoa 시스템이하는 것처럼) 서랍의 대리자 객체는 서랍 개체 자체 앞에 dealloc'd되었지만 코코아 시스템은 그러한 일이 일어나지 않도록 방지합니다 (대다수의 경우 올바르게 처리하는 것으로 보입니다).

+0

'KERN_INVALID_ADDRESS at 0x0000000000000010'이 표시 되나요? 이는 프로그램에서 대리인이 거기에 있다고 생각할 가능성이 높습니다. 가장 명백한 것은 사실이 아닙니다. – zneak

+0

오른쪽, 분명히. 질문은 * 왜 * 대리인이 아니 었습니까? – Isaac

답변

1

대리인이 먼저 알림 센터에서 등록 취소하지 않고 할당 취소 지점에 릴리스되었습니다.이 경우 위임은 알림 센터를 통해 직접 수행되는 것이므로이 경우입니다.

쉬운 해결 방법은 -dealloc 메서드에서 NSNotificationCenter's-removeObserver: 메서드를 호출하는 것입니다.


백 트레이스를 확인하십시오. 알림 센터를 통해 충돌이 발생합니다. 대개 클래스가 setDelegate:을 통해 (NIB 파일을 통해) 연결되면 알림 관찰자처럼 수행됩니다.

알림 센터와 개체 사이의 관계는 IB의 개체와 개체의 관계와 같습니다. 약한. 즉, retain이 없으므로 대리인이 너무 일찍 해제됩니다 (또는 개체를 어딘가에 너무 많이 공개 함).

어쨌든 대리인이 유용성이있는 동안 어딘가에 의해 유지되는지 확인해야합니다.

+0

델리게이트가 'NSNotificationCenter'을 통해 자체적으로 등록하는 경우, 실제로 서랍 알림을 등록하는 NSNotificationCenter의 인스턴스가 두 번 확인되었음을 이해할 수 있지만 대리인은 NIB에서 인스턴스화되고 대리인에 의해서만 참조됩니다. IBOutlet'을'NSDrawer'에서 사용하는 것입니다. 즉, 위 코드에서 위임 객체에 대한 포인터를 얻는 유일한 방법은'[theDrawerObjectOfSomeWindow delegate] '를 사용하는 것입니다. – Isaac

+0

백 트레이스/알림 센터에 대해서는 예, 알림 센터를 통과하지만 관찰하지 말았으므로 옵저버를 제거하지 않아도됩니다. (즉, 등록이 숨겨져 있으면 등록 취소가 숨겨져 있어야합니다. , 너무). http://developer.apple.com/mac/library/documentation/cocoa/conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6 인스턴스화 된 최상위 개체 NIB는 참조 카운트 된 환경에서 1의 보유 수를 가지므로 대표 오브젝트가 왜/어떻게 왜 dealloc 될지를 알 수 없습니다. – Isaac

+0

기묘하게도, 인용 된 문서에서 NIB에서 인스턴스화 된 최상위 개체를 릴리스해야한다고 말하지만 "빌드 및 분석"은 릴리스를 버그로 플래그 지정합니다. – Isaac

관련 문제