0

メモリの破損が原因と思われるクラッシュを追跡してきました。設定は C で、iOS 用の llvm を使用してビルドします。

メモリ破損は、デバッグ モードおよび最適化レベル 0 (-O0) では発生しません。コードをステップ実行できるようにするために、デバッグ シンボルを使用して再構築しましたが、最適化レベル 1 (-O1) に設定しました。クラッシュを再現するにはこれで十分で、プログラムをステップ実行できます。

問題を特定の関数呼び出しに絞り込みました。その前に、特定のポインターの値は正しいです。その後、値が破損します (値が何であれ、最終的には 0x02 になります)。

Lldb は、変数やメモリの場所を監視したくないようです。gdb に切り替えて、前述の変数のアドレスを出力しようとすると、「レジスタ $r4 にある識別子 'x' に対してアドレスが要求されました」というメッセージが表示されることがわかりました。

最適化として、コンパイラーが変数の値をレジスターに保持することを決定する場合があることを理解しています。確かに、関数呼び出しの前後に $r4 の値を出力すると、前後に正しい値 0x02 が表示されます。

私はこの時点で少し頭を悩ませており、これをより小さな問題に分割する方法がわかりません。したがって、私の質問は次のとおりです。

  1. コンパイラーが変数の値を最適化としてレジスターに格納していると仮定すると、別の関数が呼び出されたときにそのレジスターはどうなるでしょうか?

  2. 新しい関数が返されると、値が保存および復元されるメカニズムはありますか?

  3. デバッグ手法に関する推奨事項はありますか?

すべてのヘルプと提案に感謝します。このテーマに関する読み物へのリンクも大歓迎です。

ありがとう


編集:バージョン情報の追加

iOS バージョン: 5.1

llvm バージョン: i686-apple-darwin10-llvm-gcc-4.2 (GCC) 4.2.1 (Apple Inc. ビルド 5658 に基づく) (LLVM ビルド 2377.00)

Xcode バージョン: 4.3.1

Gdb バージョン: GNU gdb 6.3.50-20050815 (Apple バージョン gdb-1708)

iPhone 3Gs で実行中 (クラッシュはシミュレーターに表示されません)

4

2 に答える 2

0

可能であれば、Valgrind を使用してみてください。これは良い出発点のように見えます。

また、プログラムで -fstack-protector を有効にしてみてください。

于 2012-05-04T14:00:39.097 に答える
0

完全な回答ではありませんが、

コンパイラーが変数の値を最適化としてレジスターに格納していると仮定すると、別の関数が呼び出されたときにそのレジスターはどうなるでしょうか?

レジスターは、おそらく呼び出し先によってスタックにプッシュされるはずです。

新しい関数が返されると、値が保存および復元されるメカニズムはありますか?

呼び出し規約によって異なりますが、一般的には、スタックにプッシュした人はスタックからポップする責任があります

最後のこと:

ある最適化レベルでは「動作」し、他の最適化レベルでは動作しないというようなケースに遭遇した場合、未定義の動作が発生する可能性が非常に高くなります。コードで見つからない場合は、ここで質問して、実際のコードを提示してください。

于 2012-05-04T13:51:59.407 に答える