まず、バックトレースに call が含まれていることに注意してくださいmalloc_printerr
。この関数は理由を標準エラーに書き込みますので、キャプチャすることを忘れないでください!
新規/削除タイプの不一致、二重削除、または無効なポインターのいずれであっても、実際のバグは、実際にそれを検出する削除のずっと前に発生します。そのため、gdb はあまり役に立ちません。関連するポインターに発生したことをすべてログに記録し、問題が発生したときに掘り下げる必要があります。
- 完全に無効なポインターである場合は、初期化されていないメモリまたはバッファ オーバーランで上書きされます。すべてのオブジェクトに、関連する可能性のあるポインターをゼロにする正しいコンストラクターがあることを確認してください。どちらの問題もvalgrindでキャッチできます。バッファ オーバーランも、 DUMA ライブラリまたはマッドフラップ(gcc に同梱) を使用して、より少ないオーバーヘッド (ただし精度は低くなります) でキャッチできます。
- 二重削除の場合は、デストラクタの場合を除いて、関連するポインタを削除した後にゼロにすることを確認してください (デストラクタで削除する場合は、コンストラクタで初期化したことを確認してください)。関連するポインターのすべての操作のログ メッセージを追加し、クラッシュしたときに、ポインターが復活したように見えるログをトレース バックします。無効なポインターに対してもそれを試みることができます。
- 不一致の場合は、常に withを割り当てたときに
[]
削除し、それ以外の場合は決して削除しないようにし、常に完全な型を削除していることを確認してください (C++ は不完全な型の削除を受け入れ、未定義の動作です)。[]
[]
- 上記のいずれも、関連するポインタを保持するオブジェクトのデストラクタを適切に呼び出さないことによる二次的な影響である可能性があります。デストラクタの呼び出しに失敗すると、不適切な型のポインタを削除したり、不完全な型へのポインタを削除したり
[]
、新規と削除で不一致になったりする可能性があります。レビューに加えて、関連する可能性のあるコンストラクタとデストラクタにログを追加し、それらが適切に一致していることをログで確認します。
実際にエントリを照合できるように、ポインタ値を常にログに記録することを忘れないでください。また、ログを分析するためのスクリプトを作成する必要がある場合もあります (一致しないエントリを見つけます)。十分なスペースを確保してください。この方法で数ギガバイトのログを生成するのはかなり簡単です。
疑わしいいくつかの操作を絞り込んだら、バックトレースをログに書き込む必要がある場合があります。backtrace(3)ライブラリ関数またはlibunwindを見てください。