1. ホーム
  2. c++

[解決済み] ヒープ破壊エラーのデバッグ方法を教えてください。

2022-04-22 16:19:43

質問

Visual Studio 2008で(ネイティブ)マルチスレッドC++アプリケーションをデバッグしています。不定期に「Windows has triggered a break point..." error」と表示され、ヒープの破壊が原因である可能性があると指摘されます。これらのエラーは、すぐにアプリケーションをクラッシュさせるわけではありませんが、直後にクラッシュする可能性があります。

これらのエラーの大きな問題は、破損が実際に発生した後にポップアップ表示されることで、特にマルチスレッドのアプリケーションでは、追跡やデバッグが非常に困難になります。

  • どのようなことが原因でこのようなエラーが発生するのでしょうか?

  • デバッグの方法を教えてください。

ヒント、ツール、メソッド、啓蒙...大歓迎です。

解決方法は?

アプリケーションベリファイア と合わせて Windows用デバッギングツール は素晴らしいセットアップです。 の一部として両方を手に入れることができます。 Windowsドライバキットまたは軽量なWindows SDK . (アプリケーションベリファイアーのことは ヒープ破壊の問題についての以前の質問 .) 過去にBoundsCheckerやInsure++(他の回答で紹介)も使ったことがありますが、Application Verifierにこれだけの機能があることに驚きました。

電気柵(別名:"efence")です。 dmalloc , バルグラインド などは言及する価値がありますが、これらのほとんどはWindowsよりも*nixで実行するのがはるかに簡単です。 Valgrind はとんでもなく柔軟です。私はこれを使って、多くのヒープ問題を抱えた大規模なサーバソフトウェアをデバッグしてきました。

他のすべてが失敗したとき、あなたは独自のグローバルな演算子new/deleteとmalloc/calloc/reallocオーバーロードを提供することができます - そうする方法は、コンパイラとプラットフォームによって少し異なります - そしてこれは少し投資になるでしょう - しかしそれは長い目で見れば報われるかもしれません。 望ましい機能のリストはdmallocやelectricfenceでおなじみで、驚くほど優れた本である 確かなコードの書き方 :

  • セントリーバリュー マジックナンバーで埋める (バッファオーバーフローやアンダーフロー、たまに "wild" ポインタを捕捉するのに役立つ)。
  • アロックフィル Visual C++は、デバッグビルドで既にこの処理を行います (初期化されていないバーの使用を検出するのに役立ちます)
  • フリーフィル ほとんどの場合、デリファレンスされるとセグメンテーションフォールトを引き起こすように設計されています (ぶら下がりポインタの検出に役立ちます)。
  • ディレイフリー 解放されたメモリをしばらくヒープに戻さず、空き領域は確保するが利用できないようにする (ダングリングポインタをより多く検出し、近接するダブルフリーを検出する)
  • 追跡 割り当てが行われた場所を記録しておくと便利な場合があります。

私たちのローカルの自作システム(組み込みターゲット用)では、ランタイムオーバーヘッドがはるかに大きいため、トラッキングを他のほとんどのものから分離していることに注意してください。


これらのアロケーション関数/演算子をオーバーロードする他の理由に興味がある場合は、以下を参照してください。 グローバル演算子 new と delete をオーバーロードする理由は何ですか? ヒープ破壊のエラーを追跡するのに役立つ他のテクニックや、適用可能なツールもリストアップされています。


MSが使っているalloc/free/fenceの値を検索すると、ここで自分なりの答えを見つけてしまうので、以下は Microsoft dbgheap fill の値をカバーする別の回答 .