アプリケーションをデバイスにデプロイすると、プログラムは数サイクル後に次のエラーで終了します。
Program received signal: "EXC_BAD_ACCESS".
プログラムは、iPhoneシミュレータ上で問題なく実行されます、それはまた私が一度に一つずつ指示を踏む限りデバッグして実行されます。もう一度実行してみると、EXC_BAD_ACCESS
シグナルが表示されます。
この特定のケースでは、それはたまたま加速度センサーのコードのエラーです。シミュレータ内では実行されないため、エラーが発生しませんでした。ただし、デバイスに展開されると実行されます。
この質問に対する回答の大部分は一般的なEXC_BAD_ACCESS
エラーを扱うので、私はこれを恐ろしいBad Accessエラーのキャッチオールとして開いたままにします。
EXC_BAD_ACCESS
は通常、不正なメモリアクセスの結果としてスローされます。あなたは以下の答えでより多くの情報を見つけることができます。
あなたは以前にEXC_BAD_ACCESS
シグナルに遭遇しましたか、そして、あなたはそれをどのように扱いましたか?
あなたの説明から最も可能性の高い説明はあなたのメモリ管理に何らかのエラーがあるということです。あなたは数週間iPhone開発に取り組んできましたが、Objective C全般について経験したかどうかではありません。もしあなたが別の背景から来たのであれば、あなたが本当にメモリ管理ルールを内部化する前に少し時間がかかるかもしれません - あなたがそれを大事にしない限り。
割り当て関数(通常は静的割り当てメソッドですが、他にもいくつかあります)、またはコピーメソッドから取得したものはすべてメモリを所有しているため、完了したら解放する必要があります。
しかし、あなたが何か他のものから何かを取り戻すのであれば含むファクトリメソッド(例えば[NSString stringWithFormat]
)あなたは自動解放参照を持つことになるでしょう。あなたがそれを保持していることを直接の機能を超えてそれを周りに保つ必要があるならばそれは重要です。そうしないと、エミュレータのテスト中にメモリが使用中に割り当てられたままになったり、解放されてもまだ有効である可能性がありますが、解放されてデバイス上で実行すると不正アクセスエラーとして表示されます。
これらのことを突き止めるための最善の方法は、とにかく(明らかな問題がない場合でも)特にLeaksオプションを使用してInstrumentsツールでアプリを実行することです。
EXC_BAD_ACCESSの主な原因は、解放されたオブジェクトにアクセスしようとしたことです。
これを解決する方法を見つけるためには、この資料を読んで下さい: DebuggingAutoReleasePool
あなたが「自動解放されたオブジェクトを解放する」と思っていなくても、これはあなたに適用されます。
この方法は非常にうまくいきます。いつも大活躍しています。
まとめると、これはCocoaのNSZombieデバッグクラスとコマンドラインの "malloc_history"ツールを使用して、コード内でアクセスされたリリース済みオブジェクトを正確に見つける方法を説明しています。
サイドノート:
Instrumentsを実行してリークをチェックしてもEXC_BAD_ACCESSのトラブルシューティングには役立ちません。私はメモリリークがEXC_BAD_ACCESSとは何の関係もないことを確信しています。リークの定義は、もうアクセスできないオブジェクトなので、呼び出すことはできません。
更新:リークをデバッグするためにInstrumentsを使用します。 Xcode 4.2から、製品 - >プロファイルを選択し、Instrumentsが起動したら、 "Zombies"を選択してください。
EXC_BAD_ACCESSシグナルは、無効なポインタをシステムコールに渡した結果です。私はOS X上でテストプログラムを使って今日のうちの1つを手に入れました - 私は初期化されていない変数をpthread_join()
に渡していました。
私はiPhoneの開発には慣れていませんが、システムコールに渡すすべてのバッファポインタを再確認する必要があります。コンパイラの警告レベルをずっと上げてください(gccでは、-Wall
および-Wextra
オプションを使用してください)。シミュレータ/デバッガでできるだけ多くの診断を有効にします。
私の経験では、これは通常違法なメモリアクセスが原因です。すべてのポインタ、特にオブジェクトポインタを調べて、それらが初期化されていることを確認してください。 MainWindow.xibファイルを使用している場合は、それがすべての必要な接続で正しく設定されていることを確認してください。
紙上でのチェックで何も起こらず、シングルステップでは起こらない場合は、NSLog()ステートメントを使ってエラーを探します。原因となっている行を特定するまでコードを振りかけます。エラー。その後、その行にブレークポイントを設定してプログラムを実行します。ブレークポイントに到達したら、すべての変数とその中のオブジェクトを調べて、期待していないものがないかどうかを確認します。特に、オブジェクトクラスが予期しないものである変数には注意してください。変数にUIWindowが含まれていても、その代わりにNSNotificationが含まれていると、デバッガが動作していないときに同じ根本的なコードエラーが異なる方法で現れる可能性があります。
数時間かけてEXC_BAD_ACCESSを追跡したところ、NSZombiesやその他の環境変数で何も言われていないようでした。
私にとっては、それはフォーマット指定子を持つが引数が渡されていない愚かなNSLogステートメントでした。
NSLog(@"Some silly log message %@-%@");
によって固定
NSLog(@"Some silly log message %@-%@", someObj1, someObj2);
完全な答えではありませんが、これを受け取った特定の状況の1つは、autoreleaseを使用しようとしたために「死んだ」オブジェクトにアクセスしようとしたときです。
netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease];
例えば、私は実際にこれを 'notify'のオブジェクトとして渡していました(リスナー、オブザーバー、あなたが好きなイディオムとして登録しました)が、通知が送信されればそれはもう死んでいますこれを[[MyNetObject alloc] init]
に変更し、後で適切にリリースすることでエラーを解決しました。
これが起こるかもしれないもう一つの理由は、例えば、あなたがオブジェクトを渡して、それを保存しようとする場合です:
myObjectDefinedInHeader = aParameterObjectPassedIn;
後でmyObjectDefinedInHeaderにアクセスしようとすると、問題が発生する可能性があります。使用方法
myObjectDefinedInHeader = [aParameterObjectPassedIn retain];
あなたが必要なものかもしれません。もちろん、これらは私が遭遇したもののほんの2、3の例です、そして、他の理由があります、しかし、これらはとらえどころのない証明することができるので、私はそれらに言及します。がんばろう!
2010年WWDCビデオは、アップルの開発者プログラムのすべての参加者に公開されています。素晴らしいビデオがあります。「セッション311 - 計測器を使った高度なメモリ解析」では、計測器でゾンビを使用したり、他のメモリ問題をデバッグしたりする例をいくつか紹介します。
ログインページへのリンクは HERE をクリックしてください。
これが起こり得る別の状況を追加するためだけに:
私はコードを持っていました:
NSMutableString *string;
[string appendWithFormat:@"foo"];
明らかに私は文字列にメモリを割り当てるのを忘れていました:
NSMutableString *string = [[NSMutableString alloc] init];
[string appendWithFormat:@"foo"];
問題を修正しました。
Objc_exception_throwにブレークポイントを設定すると便利です。そうすれば、EXC_BAD_ACCESSを受け取ったときにデバッガは壊れるはずです。
指示はここで見つけることができます DebuggingTechniques
例外が発生する前にEXC_BAD_ACCESS例外をキャッチするもう1つの方法は、XCode 4以降で 静的アナライザ です。
Product> Analyze(shift + cmd + B)でスタティックアナライザーを実行します。アナライザによって生成されたメッセージをクリックすると、問題のオブジェクトの保持/解放の順序を示す図がソース上にオーバーレイされます。
「あなたが割り当てたり保持したりしなかった場合は、解放しない」という単純な規則を使用してください。
上記のリンクをチェックして、それが言うようにしてください.... NSZombiesを使うためのちょうどいくつかの簡単な指示
アプリケーションを実行し、失敗した後( "EXC_BAD_ACCESS"ではなく "中断"を表示する必要があります...コンソールを確認します([実行]> [コンソール])...アクセスしようとしているオブジェクトを示すメッセージが表示されます)。
- ベン
大きな配列を含むCメソッドを実行しようとしたときにだけ、iPhoneでEXC_BAD_ACCESSが発生しました。シミュレータはコードを実行するのに十分なメモリを私に与えることができましたが、デバイスはそうではありませんでした(配列は100万文字だったので、それは少し過剰でした!).
EXC_BAD_ACCESSはメソッドのエントリポイントの直後に発生しましたが、配列宣言の近くにはないため、しばらくの間私を混乱させました。
たぶん他の誰かが私の2、3時間の引っ張りから利益を得るかもしれません。
私はinitメソッドで自分自身を返すのを忘れていました...;)
これは素晴らしいスレッドです。これが私の経験です。プロパティ宣言でretain/assignキーワードをめちゃめちゃにしました。私は言った:
@property (nonatomic, assign) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, assign) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, assign) IBOutlet UISwitch *asiaSwitch;
私が言ったべき場所
@property (nonatomic, retain) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, retain) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, retain) IBOutlet UISwitch *asiaSwitch;
EXC_BAD_ACCESSの扱い方
EXC_BAD_ACCESSエラーがスローされたときにxcodeがmain.mクラスのエラーを表示し、クラッシュが発生した場所に関する追加情報を表示しないと感じることがあります(たまに)。
そのような時には、Xcodeで例外ブレークポイントを設定して、例外がキャッチされたときにブレークポイントが配置され、その行でクラッシュが発生したことをユーザーに直接知らせることができます。
私は過去4時間、このエラーを解決するためにコードのデバッグとリファクタリングを行ってきました。上記の投稿で私は問題を見ました。
前のプロパティ:startPoint = [[DataPoint alloc] init]; startPoint = [DataPointList objectAtIndex:0];
。 。 x = startPoint.x - 10。 // EXC_BAD_ACCESS
以下のプロパティ:startPoint = [[DataPoint alloc] init]; startPoint = [[DataPointList objectAtIndex:0]保持];
さようならEXC_BAD_ACCESS
dealloc
から割り当てられていないポインタを取り出すのを忘れていました。私はUINavigationControllerの私のrootViewでexc_bad_accessを取得していました、しかし時々だけ。 rootViewのviewDidAppear {}の途中でクラッシュしていたため、この問題はrootViewにあると思いました。それは私が悪いdealloc {}リリースでビューをポップした後にのみ起こることが判明しました、そしてそれはそれでした!
"EXC_BAD_ACCESS" [プロセス330への切り替え]今すぐプログラムに使用できるメモリがない:mallocを呼び出すのは危険です。
割り当てようとしていたのは問題だと思っていましたが、割り当てられていないものを解放しようとしていたのではありません。
完了したら、文字列を解放してください。
私はこれがしばらく前に尋ねられたことを理解しています、しかしこのスレッドを読んだ後、私はXCode 4.2のための解決策を見つけました:製品 - >スキームの編集 - >診断タブ - > Enable Zombie Objects
割り当て解除されたオブジェクトに送信されているメッセージを見つけるのに役立ちました。
無限再帰があるとき、私はあなたがこのエラーを持つこともできると思います。これは私の場合です。
私はちょうどこの問題を抱えていました。私にとっては、その理由は、Core Data管理対象オブジェクトを削除し、後で別の場所からそれを読み込もうとしたためです。
私は過去4時間、このエラーを解決するためにコードのデバッグとリファクタリングを行ってきました。上記の投稿で私は問題を見ました。
前の物件:
startPoint = [[DataPoint alloc] init] ;
startPoint= [DataPointList objectAtIndex: 0];
x = startPoint.x - 10; // EXC_BAD_ACCESS
以下の物件:
startPoint = [[DataPoint alloc] init] ;
startPoint = [[DataPointList objectAtIndex: 0] retain];
さようならEXC_BAD_ACCESS
ご回答ありがとうございます。私は一日中この問題に苦しんでいます。あなたはすごい!
追加するだけ
Lynda.com という素晴らしいDVDがあります。
そして第6章、レッスン3は、EXEC_BAD_ACCESSとゾンビを使った作業についてのすべてです。
エラーコードだけでなく、リリースされたオブジェクトに関するより多くの情報を得るためにZombiesをどのように使うことができるのか理解するのは私にとって素晴らしいことでした。
エラーの原因を確認する
NSZombieEnabledを使用してください。
アプリケーションでNSZombieEnabled機能を有効にするには
[プロジェクト]> [アクティブな実行可能ファイルの編集]を選択して、実行可能情報ウィンドウを開きます。引数をクリックします。 「環境に設定する変数」セクションの追加(+)ボタンをクリックします。 「名前」列にNSZombieEnabledと入力し、「値」列にYESと入力します。 NSZombieEnabledエントリのチェックマークがオンになっていることを確認してください。
私はこの答えをiPhoneSDKで見つけました
メソッドパラメータを検証するためのNSAssert()呼び出しは、追跡して同様にnilを渡さないようにするのに非常に便利です。
あなたが何かをする前に、試すべきです:
プロダクト - >クリーン
そしてまた走りなさい。それは私のために働きました。そうでなければ、私は何時間も無駄にしていたでしょう。
私は[self performSegueWithIdentifier:sender:]
と-(void) prepareForSegue:(UIstoryboardSegue *)
を使っていなかったのでそれを得ましたright
さらに別の可能性:キュー内のブロックを使用していると、この時点で既に割り振り解除されている別のキュー内のオブジェクトにアクセスしようとすることが容易に起こるかもしれません。通常、GUIに何かを送信しようとしたとき。例外ブレークポイントが奇妙な場所に設定されている場合は、これが原因である可能性があります。
XCode 4以降では、Instrumentsでは非常にシンプルになっています。インストゥルメントでゾンビを走らせるだけです。このチュートリアルはそれをよく説明しています: デバッグexc_bad_accessエラーxcodeの計測器
文字列を作成するときは@
記号を忘れないでください。C-strings
をNSStrings
として扱うとEXC_BAD_ACCESS
が発生します。
これを使って:
@"Some String"
これよりもむしろ:
"Some String"
PS - 通常、array
の内容に多数のレコードを取り込む場合。
私の場合は、tableviewの削除操作が原因でした。このソリューションは私の悪いアクセスの例外を解決しました: https://stackoverflow.com/a/4186786/538408