ViewController respondsToSelector:割り当て解除されたインスタンスに送信されるメッセージ(クラッシュ)


95

さて、ここに取り引きがあります、私私のデバッグとクラッシュについての質問を出すのが嫌いです。通常は自分で処理しますが、すでに複数の質問を表示した後でも、これを回避することはできません

わかりましたので、ここに問題があります。このスタックトレースでアプリがランダムにオン/オフにクラッシュすることがわかります。

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

どこViewController時々 、私のコードがクラッシュした場所を変えることができ、持っているNOのその特定の関連性をViewControllerし、所有していないか、それを呼び出します。

また、そのコンソールトレースを取得するために、ゾンビを有効にしましたobjc_msgSend。しかし、それがどこにあるのかわかりません...私は本当に行き詰まっています!通常、私は常にクラッシュをデバッグするので、私は本当にこれで立ち往生しています。

繰り返しますが、これはさまざまな場所でさまざまなタイミングで、オンとオフでクラッシュします。そして、それがクラッシュした場所はほとんど持っていないとの関連性をViewController。そして、これは非常に混乱します。

私のコードが必要ですか?私が持っているたくさんのファイルを、それが別の場所にクラッシュされているので、私のコードを配布することは混乱になります!

運が悪いのにシンボリックブレークポイントを追加しようとしましたが、iOSのInstrumentsアプリケーションではZombiesを使用できません。サポートされていないアーキテクチャフレームワークがあるため、シミュレータでアプリを実行できません。

みんな、ありがとう...


:あなたはこの質問を見たstackoverflow.com/questions/1585688/...
セルフ

ビューへの移行方法に一貫性があると仮定すると、1つまたは2つの例を示すことができます。標準のpush / presentViewController呼び出しを実行している場合は問題ありませんが、ビューコントローラーのalloc / initのようなものを実行しているのに、push / presentを実行せずにコントローラーのサブビューとして表示します。ただのランダムな例です。しかし、コードがなければこれを診断することはできません。うまくいけば、いくつかのスニペットが何が起こっているのかを理解するのに役立つので、見てみましょう。
Rob

シンボリックブレークポイントを有効にしますか?これらを追加してみてください:wiki.zemingo.com/index.php
title

@RobertRyan presentModalViewControllerを使用していますが、サブビューとして追加しません
MCKapur

私の場合、子ビューコントローラーにはwebViewが含まれており、子VCはwebViewのscrollViewのデリゲートでした。dealloc / viewWillDisappear中にデリゲート参照を手動で削除する必要がありました。そうしないと、このクラッシュが発生しました。それが誰かを助けることを願っています。
Dermot 2015

回答:


169

Instrumentsを使用して、割り当て解除されたインスタンスエラーを追跡します。アプリケーションのプロファイルを作成し(Cmd ⌘+ I)、ゾンビテンプレートを選択します。アプリケーションの実行後、アプリケーションをクラッシュさせてみてください。あなたはそのようなものを得るはずです:

ここに画像の説明を入力してください

ポップオーバーのアドレスの横にある矢印をクリックして、割り当て解除後に呼び出されたオブジェクトを表示します。

ここに画像の説明を入力してください

これで、変更されたすべての呼び出しで、このオブジェクトの保持カウントが表示されます。これは、メッセージを直接保持/解放し、自動解放プールを排出するか、NSArrayに挿入するためです。

RefCt列は、アクションが呼び出された後、retainCountを示し、Responsible Callerは、それが実行されたクラス名とメソッドを示します。保持/解放をダブルクリックすると、インストゥルメントはこれが実行されたコード行を表示します(これが機能しない場合は、それを選択し、拡張詳細ペインで対応するものを選択することで呼び出しを調べることができます):

ここに画像の説明を入力してください

これにより、オブジェクトのすべてのretainCountライフサイクルを調べることができ、おそらくすぐに問題が見つかります。あなたがしなければならないすべては最新のリリースのために欠けているretainを見つけることです。


3
特に問題は最新のものreleaseではない可能性があります。問題は不均衡releaseです。私はまた、retainあなたがポインタを保持し、後で参照している何かの失敗である可能性もあります。
Ken Thomases

1
また、私はゾンビインストゥルメントテンプレートを持っていません
。XcodeBeta

2
ああ、ゾンビはiOSシミュレーターでのみ提供されます。iOSシミュレーターでは実行できません。使用しているフレームワークとライブラリーの一部がアーキテクチャーをサポートしていません
MCKapur

ほんの小さなメモ。これは、xcode 5の新機能によるものです。「ゾンビインスツルメントテンプレートはXcode 5で拡張され、デバイスでの使用をサポートするようになりました。デバイスでゾンビを使用するにはiOS 7が必要です。」このメモは私とあなたの2時間の貴重な時間をもたらしました...
ニックフォックス

2
このインストゥルメントをフックしたときに、アプリクラッシュしなくなり、「割り当て解除されたインスタンスにメッセージが送信されました」というエラーが表示されなくなるとはどういう意味ですか?(患者に「診断テスト」が行われると、「病気」が消えるかのようです。)
Praxiteles 14年

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

投稿してくれてありがとう、同じ問題がありました^^
Tyron

このような苛立たしい問題の解決策をどのように見つけますか?脱帽 !!
ViruMax、2015年

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で計測器を実行するには、プロジェクトのポップアップ->スキームの編集...プロファイル->計測器を選択し、割り当てまたはリークを選択してから、アプリのプロファイルを作成し、計測器を停止して、割り当ての情報ボタンをクリックし、「NSZombie検出を有効化」します。 。

ただし、com.apple.main-threadから直接送信されるメッセージの場合、おそらく何も明らかになりません。

私はこれに2時間以上ぶつけましたが、答えは過剰リリースであることがわかりました。これは、犯人が見つかるまで、プロジェクトのコピーをブルートフォースでコメントアウトして発見しました。

[viewController release];
viewController = NULL;

問題は、リリースが変数をNULLに設定しないことです。

つまり、これをNULL呼び出しに設定すると、再度解放され、refcountが減分されて、viewControllerを参照する変数が終了するまですぐにメモリが解放されます。

したがって、ARCを有効にするか、プロジェクトでリリースまたはNULLを常に使用しているが、両方を使用していないことを確認してください。私の好みはNULLを使用することです。ゾンビを参照する可能性はありませんが、オブジェクトが解放された場所を見つけるのが難しくなります。


4

私は昨日iOSで同じ問題に遭遇しました。アプリの「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のようなプロパティオブジェクトは問題を作成する可能性があるため、デリゲートを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.