あなたが提供するドキュメントを考えるとarch/i386/mm/fault.c
、エラーコード 4 は「ページのユーザーモード読み取りが見つかりません」に対応します。コード 4 のバイナリ表現 = 100。ビット 2 が最上位 (左端) ビットです。
SIGSEGV
これは、 aに aを受け取る最も一般的な原因でdelete
ある二重解放 (すでに解放されているポインターを解放しようとする) と一致します。ただし、ヒープの破損 (たとえば、他の何かを二重に解放したり、別の場所でバッファ オーバーフローや範囲外エラーが発生したりした場合) が原因である可能性があります。
valgrind
メモリ割り当てルーチンのデバッグ バージョン (MALLOC_CHECK_
バイナリを実行する前に環境内で 1 または 2 に設定) の下でコード (デバッグ シンボルでコンパイル) を実行するか、それを使用して実行してみてください。これらのエラーをキャッチして報告しようとする 2 つの異なるアプローチそれらが作られたらすぐにあなたにそれらを。
valgrind
メモリ モデルが網羅されており、適切な量のチェックをオンにすると、ほぼ確実に問題の原因を突き止めることができます。
MALLOC_CHECK_
glibc の内部にあり、他のほとんどのメモリ デバッグ インストルメンテーション ツールと同様に、valgrind
特定のタイプの比較的一般的なエラーのみをキャッチし、場合によってはヒープの破損を検出できます。そこに似た他のツールMALLOC_CHECK_
(Electric Fence など) はたくさんありますが、前者は既に C ライブラリに組み込まれており、他のツールはせいぜいライブラリ (主に含まれてオーバーライドするもの) が動的である必要がmalloc
ありfree
ます。を使用して C ライブラリの前にリンクされますLD_PRELOAD
。
ヌル ポインターでC++ を使用delete
することは技術的には問題ではないことに注意してください。そのため、チェックリストから削除することができます (削除する前にコードを明示的にチェックするようにコードを変更することにより、おそらく既にお持ちだと思います)。
詳細:
「ページのユーザー モード読み取りが見つかりません」に対応するエラー コードは、メモリへのポインター (仮想アドレス空間のどこかを参照する 32/64 ビットの数値) が逆参照されたことを意味します (つまり、一部のコードがページを読み取ろうとしました)。ポインタが保持していた仮想メモリアドレスの値) しかし、カーネルページテーブルは、仮想アドレスが、プロセスにマップされていないか、そのポインタが有効だったためにプロセスからマップ解除された [メモリの] ページを参照していることを示しています. これが起こることを想像する明白な方法は別として、破損したヒープ (舞台裏であらゆる種類の簿記情報を含む) が原因で間接的に発生する可能性があります。たとえば、渡した値に対してポインター演算が行われる場合があります。delete
ヒープ内部の以前に破損した別のポインターを使用すると、ポインターに無効な値が存在し、コードがそれを使用しようとするのを待つだけになります。
つまり、カーネル エラー コードは、一般的なデバッグ シナリオではあまり役に立ちません。
プログラムを実行しgdb
、クラッシュの数行前にブレークポイントを設定して、削除されるポインターの値と残りの周囲の状態を観察したとします。
編集:
-g2
どうやら を意味していたときの誤った参照を削除しMALLOC_CHECK_
ました。さらなる診断の質問と説明を追加しました。