2017-05-14 17 views
0

가비지 수집에서 문서 기반 응용 프로그램을 변환하는 중입니다 (10.6 미만에서 실행 됨) 자동 참조 계산 (10.12 용으로 컴파일 및 실행하려고 시도). 마지막 창을 닫을 때 일관된 EXC_BAD_ACCESS가 표시됩니다. 정적 분석기로 아무 것도 표시되지 않습니다.NSDocument 창을 닫을 때 (ARC 사용 가능)

필자는 좀비를 찾기 위해 Instruments를 사용했으며, 실제로는 할당 해제 된 개체에 release 메시지가 전송 된 것으로 보입니다. 여기에 추적은 다음과 같습니다

# Event ∆ RefCt Timestamp  Responsible Library/Responsible Caller 
173 Release -1 3 00:05.226.677 Foundation __48-[NSFileAccessArbiterProxy removeFilePresenter:]_block_invoke 
174 Release -1 2 00:05.226.679 Foundation -[NSFilePresenterXPCMessenger invalidate] 
175 Retain +1 3 00:05.226.823 Foundation -[NSBlockOperation initWithBlock:] 
176 Retain +1 4 00:05.226.858 AppKit -[NSDocument close] 
177 Release -1 3 00:05.227.350 Foundation -[NSFilePresenterXPCMessenger dealloc] 
Retain/Release (2) 00:05.227.484 AppKit -[NSDocumentController removeDocument:] 
180 Release -1 2 00:05.227.485 AppKit -[NSDocumentController removeDocument:] 
Retain/Release (2) 00:05.227.496 AppKit -[NSUIActivityManager addProvider:toUserActivity:withSetter:] 
183 Autorelease  00:05.227.499 AppKit -[NSWindowController _windowDidClose] 
184 Release -1 1 00:05.228.172 Foundation -[NSAutoreleasePool drain] 
185 Release -1 0 00:05.228.184 Foundation -[NSBlockOperation dealloc] 
186 Zombie  -1 00:05.242.579 AppKit -[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed:saveWindows:] 

이 문제를 진단하는 것은 내가 좀비로 전송되는 메시지를 볼 수 있습니다,하지만 난 물건을 공개하지 않기 때문에 (이 모든 ARC에 의해 이루어집니다)이다에서 나는 데 어려운 , 어딘가에 암묵적인 릴리스가 있다고 생각합니다. 그러나 나는 어디에서보아야할지 모르겠습니다. 디버거에서, lldb가에서 main.m에서 충돌을 호소

:

return NSApplicationMain(argc, (const char **) argv); 

어떤 도움을 크게 감상 할 수있다. 고맙습니다.

더 많은 연구를 수행 한 후 문제가 여전히 해결되지 않은,하지만 난 단서가 :

이 응답 해 주셔서 감사합니다. 예, 지금은 메모리 관리 문제라고 가정합니다. 범인을 추적하는 방법이 있습니까? 인스 트루먼 트의 좀비 사용이 도움이되는 것 같지 않습니다. 문제를 지적했지만 문제를 해결하는 데 도움이되지 않습니다. 즉, Instruments에 따른 공격 라인은 "- [NSApplication (NSWindowCache) _checkForTerminateAfterLastWindowClosed : saveWindows :]"인 것처럼 보입니다. 하지만 나는 그 라인을 발행하지 않았다. 나는 사물을 알아내는 것에 조금 진전 될 수있는 것을 만들었습니다.

나는이 문서에서 사용하고있는 구조는 다음과 같습니다

NSDocumentController : 서브 클래스하지, 기본 NSDocument : 서브 클래스, MyDocument; 창 NSWindowController의도 대표 :

MainMenu.xib 내가 다음과 같이 무기 호에 열린 창문의 대리자를 설정하려고 MyDocument.xib : 기본값은 NSWindow 를 서브 클래스하지

-(void)windowWillClose:(NSNotification *)notification 
{ 
    windowOpen = YES; 
    NSArray *windowControllers = [self windowControllers]; 
    NSWindowController *currentWindowController = [windowControllers firstObject]; 
    NSWindow *windowForCurrentController = [currentWindowController window]; 
    NSDocument *w = [windowForCurrentController delegate]; 
    [windowForCurrentController setDelegate:nil]; 
} 

이 같은 충돌이 발생합니다.

그러면 currentWindowController (또는 응용 프로그램)가 할당 취소 된 윈도우를 메시징 한 것 같습니다.

[currentWindowController setWindow:nil]; 

이가 충돌를 제거한다,하지만 (예 : 새로운 파일 등을로드 할 때와 같은) 새로운 문제를 소개 : 그래서 (위의 방법의 끝) 줄을 추가했습니다. 하지만 이것이 전체적인 문제를 해결하는 데 도움이되는지 궁금합니다.

답변

0

문제는 앱 대표가 MyDocument (NSDocument 하위 클래스)으로 설정 되었기 때문입니다.문제는 XIB에 대응 NSObject를 생성합니다 (NSApplicationDelegate 프로토콜을 구현 NSObject) 표준 AppDelegate 클래스를 만들고 AppDelegate를 입력으로 설정하고 MyDocument위한 AppDelegate 위임함으로써 해결되었다.

문제의 원인은 MyDocument 개체가 할당 취소되고있는 것 같지만 여전히 NSWindow 하위 클래스의 대리인이었습니다. 그런 다음 NSWindow은 대리인에게 dealloc 메시지를 보냈지 만 이미 할당이 취소되어 충돌이 발생했습니다.

Here is the chain that solved it (long but instructive).