2009-05-27 13 views
3

これは私をナットにしています。私はちょうど初めてApp Storeに自分の最初のアプリをアップロードしました。もちろん、私のアプリは左右に爆発しています。私がリリースビルドの設定でビルドするとき、私はランダムにいくつかの可変量の時間のためにアプリをつまんだ後EXC_BAD_ACCESSを得ます。私はゾンビを元に戻しましたが、リリースされた変数にメッセージを送信するというメッセージが表示されないので、問題は変数を過度に解放しているようには見えません。EXC_BAD_ACCESS、ゾンビはなく、デバッグビルド設定ではありません

エラーは常に自分のコード内の同じ場所に表示されます。私は正しく初期化されていない変数を保持しようとしているようです。私はそれをどうやってやっているのだろうと思っていません。

しかし、ここには奇妙なことがあります。私がデバッグリリース構成でビルドすると、決してクラッシュしません。私は一日中事を強く打つことができ、それは堅実なものです。私はリリース構成でビルドし、断続的にクラッシュします。

2つの構成のビルド設定を見ると、それほど多くの違いはありません。デバッグでは、GCC 4.0の最適化レベルは「なし」、リリースでは「最速、最小」です。リリースの最適化レベルを「なし」に切り替えると、アプリケーション自体が動作します。誰かがこれを修正するために私が探しているはずの手がかりを持っていますか?あるいは、最適化なしで配布すると、何が起こりますか?

UPDATE:

ダン!私は本当にメモリエラーのための魔法のデバッグツールが必要です。私はこのような問題を最後の日にやってきました。私は、確実にクラッシュを生成し、それを引き起こしていたコードの領域を探し始めるexerciseメソッドを追加しました。

通常、特定のタイプの操作を実行した3〜5回目にアプリケーションがクラッシュします。そのタイプの操作に関して異なる唯一のものは、アクセサリーメソッドから返された値でした。アクセサリーメソッドは一般的に0〜3の値を持つNSDecimalNumberを返しましたが、整数でない値を持つNSDecimalNumberを返すときに特別なケースが1つありました。私は非整数値を探すアクセサリーメソッドの結果をテストします。特別なケースを変更して、NSDecimalNumberを整数以外の値の代わりに-1の値に戻しました。これでアプリケーションをクラッシュさせることはできなくなりました。基本的に、私が作った唯一の変更は [[NSNumber numberWithDouble:num] decimalValue]から切り替えた

- >クラッシュ [[NSNumber numberWithInteger:num] decimalValue] へ - それは少しそれよりも複雑、しかしあまりありません>ノークラッシュ

今や、このアプリがクラッシュすることはなくなりましたが、私が行った変更は、コードの古い部分がどのようにも「壊れている」ようには見えなかったため、自信を持って私を満たしません。だから、私のアプリがもうクラッシュしないうちに、それは私がそれを "修正"したからではなく、ちょっと変わったところがありました。 8 ^(

UPDATE:プログラムがクラッシュしたときに、それは通常、それがクラッシュしたときに、デバッグコンソールには、以下を出力しないよう

デバッガは、スタックトレースを吐き出すしない:

ロードプログラムにデバッガ...

[... copyright stuff ...]

This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found). 

warning: Unable to read symbols from "UIKit" (not yet mapped into memory). 

warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found). 

warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory). 
Program loaded. 

sharedlibrary apply-load-rules all 

Attaching to program: `/Users/...', process 10066. 

Re-enabling shared library breakpoint 1 

Cannot access memory at address 0x4 

Cannot access memory at address 0x4 

(gdb) 
+0

スタックトレースを確認してください。実際に何がクラッシュしていますか? NSNumberを変更するとクラッシュするという事実は、あなたがNSNumberをどこかで過剰にリリースするかもしれないことを示唆しています。 NSNumberはクラスによってキャッシュされます。あなたが1つを過剰にリリースすると、同じ番号を表すまったく別のオブジェクトでクラッシュする可能性があります。私は値が2だったときに動作するコードを見てきましたが、 "4"のNSNumberがシステムの他の場所で過剰にリリースされたために4だったときに失敗しました。 –

+0

私はこの問題をデバッグするいくつかの問題がありました。私が理解していない理由のために、デバッガもインストゥルメンタルも私に期待している種類の情報を与えてくれません。通常、アプリケーションがクラッシュすると、デバッガはクラッシュの原因となったメソッドを誰が呼び出したかについての詳細は表示せずに、メイン実行スレッドを表示します。おそらくこれは、コンパイラがコードを最適化しているときに問題が現れるだけなので、デバッガはソースをオブジェクトコードにマッピングするのに時間がかかります。私は、デバッグのチョップが依然として基本的なものであることにも役立たないと確信しています。いつものように、私はあなたの援助に感謝します。 – ChadK

+0

しかし、スタックトレース(特に上位の数フレーム)をポストする必要があります。たとえあなたのコードが含まれていなくても、どこから問題が発生しているかについて多くの情報を与えることができます。ココアでは、しばしば、あなたのために後で実行されることを求めています。 -autoreleaseはこれの非常に一般的な例です。その "後の時間"がクラッシュすると、 "あなたのコード"はどれもスタックには入りませんが、コード内のバグが原因です。 –

答えて

2

だけならば、それはゾンビをオンにするのと同じくらい簡単だった、あなたは常にあなたの過リリースを見つけることができる...ゾンビは検出できないエラーこれらの種類がたくさんあります。メモリエラーのための魔法のデバッグツールはありません。慎重なプログラミングだけです(そして、これらのエラーをはるかに珍しくし、発生時にデバッグするのがはるかに簡単なパターンがあります)。

最適化されたコードは、最適化されていないコードには表示されない無料のものをたくさん振ることができます。それは、それがivarではなくローカル変数かもしれないが、おそらくそうでないかもしれないことを少し示唆している。それはちょうどタイミングかもしれません。より速くなると競合状態がより頻繁に逆になることがあります。

クラッシュする可能性がある場合は、スタックトレースを最初の手順として見てください。

最適化なしで配布することに深刻な問題はありませんが、問題を隠すだけです。そこにコーディングエラーがあります。最適化があなたのコードを壊すことはありません。コードが壊れています。

メモリ問題のデバッグについては、よくお読みください。here #1ルールは、アクセサを使用する必要があるということです。彼らはあなたに多くの心苦しさを救うでしょう。うまくいけば、あなたはすでにこれをやっている。私はmemory management rulesについての私の短い議論でいくつかの他の指針を提供します。

+0

ご意見ありがとうございます。私はアドバイスを感謝します。 – ChadK

1

コンパイラの警告レベルを上げて、何かポップアップがあるかどうかを確認することをお勧めします。あなたのプロジェクト設定を開き、見つけることができるすべての「警告」オプションを有効にします。または、その他のCフラグというプロジェクト設定を見つけて、フラグ-Wall -Wextraを追加します。

符号付き/符号なしのミスマッチ、精度の低下などのために、(通常は)安全に無視できるホワイトノイズがたくさんあります。しかし、あなたが間違いなく無視すべきであることを示すいくつかの重要な警告があるかもしれません:キャストのない整数からポインタを作ること(またはその逆)などです。警告を無視して100%確実でない場合は、警告が消えるようにコードを修正してください。

+0

符号付き/符号なし比較では、本当に驚くような方法であなたを焼くことができます。あなたの兆候を正しいものにする価値があります。精密なものは通常、問題を多く作成しませんが、警告をオンにして修正するだけで簡単に修正できます(定数に "f"を追加する必要があります。ダブルス)。「あなたはアクセサーを使用する」の後、コードを大幅に改善し、デバッグ時間を短縮した第2の法律は「エラーを警告として扱う」でした。 –

+0

本当に、署名付き/符号なしのミスマッチでひどく燃えることがありますが、foo.size()関数の "for(int i = 0; i

関連する問題