2015-12-02 5 views
5

私はあまりにも多くのコードを持つライブラリを作成しています。「次の行に記載された無効なアドレスに」バグ

私の問題は、Valgrindのとして分析することを、セグメンテーションフォールトです:無効なアドレスへ

ジャンプ0x72612F656D6F682Fで次の行
に述べた:??? [...](スタックコール)this question

おかげで
は、私がどこかにスタックの破損を持っているので、それがあると思います。

私の質問は:それを見つける方法ですか?
GDBを使ってみましたが、セグメンテーションフォルトが同じ場所にないようです。 GDBは関数の最初の行にあることを伝えていますが、Valgrindはそれがセグメンテーション・フォルトを作るこの関数の呼び出しだと伝えています。

+1

UB関連の問題を解決することはまったく楽しいことではなく、ヒープ/スタックの破損の並べ替えは本当に苦しいことがあります。容疑者を絞り込むプロセス(例:処理するコードのセクションを一時的に省略し、調査官のような容疑者を排除するなど)を行うための完全な組織的な方法はわかりません。私が何年にもわたって見つけたことは、これらの数が少なくなっていることです。それは後天的に発見するよりも防ぐのが簡単です。仮定を自由に、特に危険なコードの周りに置くことは有用です。あなたが低レベルの構成要素を含むたびに厳密なテストを行うことは、人生を節約することができます。 –

+1

多くのユニットテストが必要な低レベルのコンテナやメモリアロケータを作成する場合のように、テスト手順の厳格さは通常、作成する低レベルコードの量に比例します。とにかく - これはすぐに問題に役立つものではないことを恐れている - 誰かがこれらをデバッグする本当に素晴らしい方法を持っているかもしれない。 –

+1

@Ike Right、それは私のスタックのデータをオーバーライドしていた実験的なコンテナでした...アドバイスをいただきありがとうございます。 – Aracthor

答えて

4

問題が再現可能であれば、this answerと同様のテクニックを使用して、復帰アドレスの場所にウォッチポイントを設定し、壊れた命令の直後の命令でGDBを停止させることができます。

+0

@Aracthorそして答えのポイントは、それを見つける方法を正確に伝えることです。リターンアドレスがどこに格納されているか知っています*あなたが知っている*関数への入力時に正しいことを知っています。ウォッチポイントを設定すると、その場所が上書きされるとGDBが停止します。 –

+0

しかし、ウォッチポイントとして設定する必要があるリターンアドレス*の場所は何ですか? – Aracthor

+0

最適化されていないビルドがあり、 'x86_64'であれば、関数への'ステップ '(過去の関数プロローグ)で' $ rbp [1] 'に戻りアドレスが格納されます。 'x/2a $ rbp'を実行すると、以前の$ rbpとあなたの関数の呼び出し側のアドレスが表示されます。最適化されたビルドをお持ちの場合は、戻りアドレスが格納されている場所を見つけるために関数を '逆アセンブルする '必要があります。 –

関連する問題