ViewController respondsToSelector : 할당 해제 된 인스턴스로 메시지 전송 (CRASH)


95

좋아, 여기에 거래가 있습니다. 디버깅 및 충돌에 대한 질문을 제기하는 것이 싫습니다 . 보통 내가 직접 처리하지만 이미 여러 질문 을 본 후에도이 문제를 해결할 수 없기 때문 입니다.

좋아, 여기에 문제가 있습니다.이 스택 추적으로 내 앱이 무작위로 켜지고 꺼지는 것을 찾습니다.

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

어디 ViewController가끔 내 코드가 충돌 장소를 다양 할 수있다 NO의 특정 관련성을 ViewController하고 자신하지 않거나 전화.

또한 콘솔 추적을 얻기 위해 Zombies를 활성화했습니다. 그렇지 않으면 콘솔 인쇄가 전혀 표시되지 않고 다음 objc_msgSend과 같은 결과 만 얻을 수 있습니다. 이는 릴리스 된 내용을 메시징하고 ​​있음을 의미합니다. 하지만 그게 어디인지 모르겠어요 ... 정말 꼼짝 못했어요! 보통 나는 항상 내 크래시를 디버그하기 때문에 나는 이것에 정말로 붙어 있습니다.

다시 말하지만, 이것은 다른 시간에, 켜고 끄는 다른 장소에서 충돌합니다. 그리고 충돌 장소는 거의 없습니다 더 받는 관련성을 ViewController. 그리고 저는 이것이 매우 혼란 스럽습니다.

내 코드가 필요합니까? 나는이 많은 파일을하고 다른 장소에서 충돌되기 때문에, 내 코드를 배포하는 것은 엉망이 될 것이다!

운없이 상징적 인 중단 점을 추가하려고했는데 iOS 용 Instruments 응용 프로그램에서는 Zombies를 사용할 수 없습니다. 지원하지 않는 아키텍처 프레임 워크가 있으므로 시뮬레이터에서 앱을 실행할 수 없습니다.

모두 감사합니다 ...


이 질문
— self

뷰로 전환하는 방식이 일관 적이라고 가정하면 한두 가지 예를 보여줄 수 있습니다. 표준 push / presentViewController 호출을 수행하는 경우 괜찮을 것입니다.하지만 여기에서 뷰 컨트롤러 할당 / 초기화와 같은 작업을하는 많은 사람들이 있지만 푸시 / 프레젠테이션을 수행하지 않고 컨트롤러의 하위보기로보기. 임의의 예입니다. 하지만 코드 없이는이를 진단 할 수 없습니다. 몇 가지 스 니펫이 무슨 일이 일어나고 있는지 파악하는 데 도움이되기를 바랍니다.
— Rob

기호 중단 점을 활성화하는 것은 어떻습니까? 이러한 추가 시도 wiki.zemingo.com/index.php?title=Symbolic_Breakpoints을
— Stavash

@RobertRyan 나는 presentModalViewController를 사용하고, 나는 그것을 subview로 추가하지 않는다
— MCKapur

제 경우에는 자식 뷰 컨트롤러에 webView가 포함되어 있었고 자식 VC는 webView의 scrollView에 대한 대리자였습니다. dealloc / viewWillDisappear 중에 델리게이트 참조를 수동으로 제거해야하거나이 충돌이 발생했습니다. 누군가에게 도움이되기를 바랍니다.
— Dermot

답변:


169

Instruments 를 사용 하여 할당 취소 된 인스턴스 오류를 추적합니다. 애플리케이션 ( Cmd ⌘+ I)을 프로파일 링 하고 Zombies 템플릿을 선택합니다 . 응용 프로그램이 실행 된 후 충돌을 시도하십시오. 다음과 같은 결과를 얻을 수 있습니다.

여기에 이미지 설명 입력

팝 오버에서 주소 옆에있는 화살표를 클릭하면 할당이 취소 된 후 호출 된 개체가 표시됩니다.

여기에 이미지 설명 입력

이제 변경된 모든 호출이이 개체의 보유 수를 확인해야합니다. 이는 유지 / 해제 메시지를 직접 전송하고 자동 해제 풀을 비우거나 NSArray에 삽입하기 때문일 수 있습니다.

RefCt 열에는 작업이 호출 된 후 preserveCount가 표시되고 Responsible Caller 는 해당 작업이 수행 된 클래스 이름과 메서드를 표시합니다. 유지 / 해제를 두 번 클릭하면 계측기가 수행 된 코드 줄을 표시합니다 (작동하지 않는 경우 확장 세부 정보 창 에서 해당 호출을 선택하고 해당 호출을 선택하여 검사 할 수 있습니다 ).

여기에 이미지 설명 입력

이렇게하면 개체의 모든 preserveCount 수명주기 를 검사 할 수 있으며 문제를 즉시 찾을 수 있습니다. 당신이해야 할 일은 최신 릴리스에 대한 누락 된 보유 를 찾는 것입니다 .


3
특히 최신 문제가 아닐 수 있습니다 release. 문제는 어떤 불균형 release. 나는 또한 단순히 retain당신이 포인터를 유지하고 나중에 참조하는 것에 대한 실패가 될 수 있습니다 .
— Ken Thomases

1
또한 Zombie 도구 템플릿이 없습니다. Xcode Beta 4.5를 사용하고 있기 때문일 수 있습니다. 그 동안 4.4로 전환 할 것입니다
— MCKapur

2
오, 좀비는 iOS 시뮬레이터에서만 제공됩니다. 나는 아이폰 OS 시뮬레이터의 아키텍처를 지원하지 않는 사용 내 프레임 워크와 라이브러리의 일부를 실행할 수 없습니다
— MCKapur

작은 메모입니다. 이것은 xcode 5의 새로운 기능에서 가져온 것입니다. "Zombies 악기 템플릿은 Xcode 5에서 향상되었으며 이제 장치에서 사용을 지원합니다. 장치에서 좀비를 사용하려면 iOS 7이 필요합니다." 이 노트는 ... 나와 내 소중한 시간 2 시간을 가져
— nickfox

2
이 기기를 연결할 때 앱 이 충돌을 멈추고 "할당 해제 된 인스턴스로 메시지 전송 됨"오류를 표시 하지 않는다는 것은 무슨 의미 입니까? (환자가 "진단 테스트"를 받으면 "질병"이 사라지는 것과 같습니다.)
— Praxiteles

59

비슷한 문제가있었습니다. 제 경우에는 viewController가 navigationController 이벤트를 가져 오는 데 필요했기 때문에 탐색 컨트롤러 대리자로 등록했습니다.

 self.navigationController.delegate = self;

해당 컨트롤러가 할당 해제되었지만 여전히 뷰 컨트롤러의 대리자 일 때 충돌이 발생합니다. 이 코드를 dealloc에 ​​추가해도 효과가 없습니다.

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

dealloc이 호출되는 시점에서 뷰 컨트롤러는 이미 뷰 계층 구조에서 제거되었으므로 self.navigationController는 nil이므로 비교가 실패 할 수 있습니다! :-(

해결책은 실제로 그렇게하기 직전에 뷰 계층 구조를 떠나는 VC를 감지하기 위해이 코드를 추가하는 것이 었습니다. iOS 5에 도입 된 방법을 사용하여 뷰가 언제 팝업되고 푸시되지 않는지 확인합니다.

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

더 이상 충돌이 없습니다!


저도 감사합니다-이 게시물을 찾는 데 단 4 시간의 검색이 필요했습니다.
— daidai 2014

게시 해 주셔서 감사합니다. 같은 문제가 발생했습니다 ^^
— Tyron

사람들은 그러한 성가신 문제에 대한 해결책을 어떻게 찾습니까? 오프 모자 !!
— ViruMax

4

해결할 수없는 사람을 위해 다음과 같은 몇 가지 다른 기술이 있습니다.

https://stackoverflow.com/a/12264647/539149

https://stackoverflow.com/a/5698635/539149

https://stackoverflow.com/a/9359792/539149

https://stackoverflow.com/a/15270549/539149

https://stackoverflow.com/a/12098735/539149

Xcode 5에서 Instruments를 실행하려면 프로젝트 팝업-> Edit Scheme ... Profile-> Instrument를 클릭하고 Allocations 또는 Leaks를 선택한 다음 앱을 프로파일 링 한 다음 Instruments를 중지하고 Allocations에서 info 버튼을 클릭하고 "Enable NSZombie Detection"을 클릭합니다. .

그러나 com.apple.main-thread에서 직접 오는 메시지의 경우 아무 것도 표시하지 않을 것입니다.

나는 이것에 대해 두 시간 이상 머리를 두 드렸고 그 대답은 과다 릴리스로 판명되었는데, 범인을 찾을 때까지 무차별 대입으로 내 프로젝트 사본을 주석 처리하여 발견했습니다.

[viewController release];
viewController = NULL;

문제는 릴리스가 변수를 NULL로 설정하지 않는다는 것입니다.

즉, NULL 호출로 설정하면 다시 릴리스되고, refcount를 줄이고 나중에 viewController를 참조하는 변수가 완료 될 때까지 메모리를 해제합니다.

따라서 ARC를 활성화하거나 프로젝트가 릴리스 또는 NULL을 일관되게 사용하는지 확인하십시오. 내가 선호하는 것은 NULL을 사용하는 것이다. 왜냐하면 좀비를 참조 할 기회가 없기 때문에 개체가 풀린 곳을 찾기가 더 어려워지기 때문이다.


4

어제 iOS에서 같은 문제를 만났습니다. App "About"하위보기에서 IAP를 만들고 "About"viewDidLoad에 Transaction Observer를 추가했습니다. 처음 구매할 때 문제 없습니다. 메인 창으로 돌아가서 다시 구매할 서브 뷰에 대해 입력 한 후 "할당 해제 된 인스턴스로 메시지 전송"문제가 발생하고 앱이 충돌했습니다.

- (void)viewDidLoad
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];                                           object:nil];
}

dealloc에서 Transaction Observer를 제거하면 문제가 해결됩니다.

- (void)dealloc
{
    // Even though we are using ARC, we still need to manually stop observing any
    // NSNotificationCenter notifications.  Otherwise we could get "zombie" crashes when
    // NSNotificationCenter tries to notify us after our -dealloc finished.

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

그것은 내 런타임 충돌 zombie을 고쳤습니다 ... 나는 인앱 구매에 대한 개체를 얻었습니다. 많은 시간을 파헤친 후 나는 이것을 발견했다 .... 큰 감사합니다.
— Mahendra

4

나는 매우 유사한 문제가 있었고 그것이 내비게이션 컨트롤러 델리게이트 세트 때문이라는 것을 알았습니다.

아래는 내 문제를 해결했습니다.

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.navigationController.delegate != self) {
        self.navigationController.delegate = self;
    }
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.navigationController.delegate == self) {
        self.navigationController.delegate = nil;
    }
}

감사!! 여기서도 같은 문제였습니다.
— pegpeg

2

OS X에서 동일한 문제가 발생했습니다.

이 문제를 해결하려면 - (void)dealloc@SoftwareEvolved가 이미 말했듯 이 충분하지 않습니다 . 그러나 불행히도 - (void)viewWillDisappear버전 10.10 이상에서만 사용할 수 있습니다.

내 NSViewController 하위 클래스에 모든 좀비 위험 참조를 nil로 설정하는 사용자 지정 메서드를 도입했습니다. 제 경우에는 NSTableView속성 ( delegate및 dataSource)이었습니다.

- (void)shutdown
{
  self.tableView.delegate = nil;
  self.tableView.dataSource = nil;
}

그게 다야. 수퍼 뷰에서 뷰를 제거 할 때마다이 메서드를 호출해야합니다.


2

같은 문제가 있었는데 어떤 델리게이트가 문제를 일으키는 지 찾기가 어려웠습니다. 어떤 줄이나 코드 문도 나타내지 않기 때문에 어떤 식 으로든 시도해 보았습니다.

  1. xib 파일을 열고 파일 소유자에서 "연결 검사기 표시"오른쪽 메뉴를 선택합니다. 델리게이트가 나열되며 의심되는 nil로 설정합니다.
  2. (내 경우와 동일) Textfield와 같은 Property Object가 문제를 일으킬 수 있으므로 대리자를 nil로 설정하십시오.
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.