Visual Leak Detector を使用してメモリ リークのトラブルシューティングを行う

目次

1. VLD ツールの概要

2.VLDをダウンロードしてインストールします

2.1. VLDをダウンロードする

2.2. VLD のインストール

3. VLD インストール ディレクトリとファイルの説明

3.1. インストールディレクトリとファイルの説明

3.2. 32ビット版と64ビット版の詳細説明

4. プロジェクトに VLD を導入する

5. メモリリーク検出の説明例

5.1. プログラム起動時のエラー

5.2. デバッグを開始してメモリリークレポートを表示する

5.3. vld.ini 設定ファイルの使用

6. 最後に


VC++ の共通機能開発の概要 (コラム記事のリスト、購読歓迎、継続的な更新...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585 C++ ソフトウェア異常トラブルシューティング チュートリアル シリーズ入門から習熟まで(コラム記事一覧)、ぜひ購読して更新を続けてください...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931入門から習熟までのC++ソフトウェア解析ツール事例集(コラム)記事は更新中...) icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795 C/C++ の基礎と上級 (コラム記事、継続的に更新中...) icon-default.png?t=N7T8https://blog.csdn.net /chenlycly/category_11931267.html       メモリ リークは C/C++ プログラムでよくある問題ですが、メモリ リークはより有害であり、メモリ リークが長時間続くとメモリ不足例外が発生し、プログラムがクラッシュしてクラッシュします。大規模なソフトウェアの場合、多くのビジネス モジュールと複雑な設計があるため、トラブルシューティングが非常に困難であり、複数のトラブルシューティング方法を使用して特定するのが難しい場合があります。メモリ リークのトラブルシューティングには複数の方法を習得する必要があります。問題が発生し、1 つの方法で問題を特定できない場合は、他の方法を使用してトラブルシューティングを試みることができます。今日は、メモリ リーク ツールである Visual Leak Detector (略して VLD) を紹介し、このツールを使用してメモリ リークのトラブルシューティングを行う完全なプロセスについて詳しく説明します。この記事では、私の友人の多くが初心者の開発者であることを考慮して、より詳しく説明します。

1. VLD ツールの概要

        Visual Leak Detector は、C/C++ 用の無料のオープンソース メモリ リーク検出ツールです。他のメモリ リーク検出ツールと比較すると、メモリ リークを検出する際に次のような特徴があります。

1) メモリ リーク ポイントのコール スタックを出力でき、特定のファイル名とコード行番号が関数コール スタックに表示されます; 2) リークしたメモリ内の
完全なデータを表示できます;
3) 表示されません独立して実行される exe プログラムですが、DLL ダイナミック ライブラリである場合は、ライブラリをプロジェクトに導入してコードを再コンパイルする必要があります; 4) ソース コードはオープン ソースであり、
GNU ライセンスの下でリリースされており、詳細なドキュメントとコメントが含まれています。ヒープ メモリ管理とメモリ リークのトラブルシューティング メカニズムについて詳しく知りたい読者にとっては、最適な選択肢です。

       使用の観点から見ると、VLD はシンプルで使いやすく、ユーザーにとっては、コードに VLD のヘッダー ファイルが含まれており、VLD dll ライブラリが exe メイン プログラムのディレクトリにコピーされている限り、プログラムを検出できます。デバッグ中にプログラムを通常どおり実行すると、メモリ リークの問題が発生します。研究の観点から見ると、VLD ソース コードはオープン ソースであり、ソース コードを詳しく調べると、ヒープ メモリの断片化と解放の原理、メモリ チェックの原理、マシン メモリ操作の一般的な手法を学ぶことができます。

2.VLDをダウンロードしてインストールします

       VLD の最新バージョンは 2.5.1 です。VLD の公式ページにアクセスして、このバージョンをダウンロードしてください。

2.1. VLDをダウンロードする

以下に示すように、VLD に関する Microsoft の公式ページ ( https://marketplace.visualstudio.com/items?itemName=ArkadyShapkin.VisualLeakDetectorforVisualC )       を見つけた場合:

「Get Stated」ボタンをクリックして、VLD の github ページにアクセスします。

ページ下部にある vld-2.5.1-setup.exe のハイパーリンクをクリックしてダウンロードします。ダウンロードは途中で失敗します。

 次のように、https://kinddragon.github.io/vld/ページ       に移動し、[インストーラーをダウンロード] ボタンをクリックしてダウンロードできます 。

2.2. VLD のインストール

       まず、Web サイトにアクセスして Visual Leak Detector 2.5.1 の最新バージョンのインストール パッケージをダウンロードし、ダウンロード後直接インストールします。インストール プロセス中に、VLD を環境変数と Visual Studio に追加するかどうかを選択するように求められます。ここでチェックする必要はありません。自動的に構成する必要はありません。 VLD を使用する必要がある場合にプロジェクトを作成します。

3. VLD インストール ディレクトリとファイルの説明

       VLD は、独立して実行される exe プログラムではなく、dll ライブラリです。したがって、VLD インストール パッケージには、VLD によってコンパイルされた .h ヘッダー ファイル、.lib および .dll ライブラリ ファイルが含まれています。実行可能な exe プログラムはインストールされません。リリースするだけです。これらをインストールディレクトリにコピーします。

3.1. インストールディレクトリとファイルの説明

       VLD はデフォルトでパス C:\Program Files (x86)\Visual Leak Detector にインストールされます。インストール ディレクトリに移動して確認してください。このディレクトリには主に 3 つのフォルダが含まれています。

        インクルード フォルダーには、次のような VLD ライブラリのヘッダー ファイルが含まれています。

       vld.lib ファイルは lib フォルダーに保存されており、Win32 用の vld.lib と Win64 用の vld.lib の 2 つのバージョンがあります。dll などのバイナリ ファイルは、以下に示すように bin フォルダーに保存されます。

32 ビット版と 64 ビット版もあります。

       libcurl オープン ソース コードをコンパイルするときにも同様のインストール パッケージが使用されます。libcurl ライブラリは openssl オープン ソース ライブラリ インターフェイスを内部的に呼び出しますが、openssl ライブラリは libcurl ライブラリ ソース コードでは提供されません。openssl インストール パッケージは、次の場所からダウンロードできます。このインストールパッケージには openssl のライブラリ ファイルとヘッダ ファイルが含まれており、リリースされたライブラリ ファイルとヘッダ ファイルはインストール ディレクトリにあります。

3.2. 32ビット版と64ビット版の詳細説明

        IDE を使用して Windows プログラムをコンパイルする場合、32 ビット (x86 に相当) または 64 ビット (x64 に相当) をコンパイルできます。32 ビット Windows システムでは 32 ビット プログラムのみを実行でき、64 ビット プログラムは実行できません。64 ビット Windows システムは、64 ビット プログラムまたは 32 ビット プログラム (32 ビット プログラムとの互換性を提供) を実行できます。

        古い W​​indows システムはまだ 32 ビットである場合があります。たとえば、一部の Win7 システムはまだ 32 ビットです。ただし、比較的新しい Win10 および Win11 システムはすべて 64 ビット システムです。32 ビット Windows システムと互換性を持たせるために、多くのソフトウェアはソフトウェアを 32 ビット プログラムに直接コンパイルし、プログラムが 32 ビットと 64 ビットの両方の Windows システムで実行できるようにします。

       32 ビット インストール パッケージと 64 ビット インストール パッケージを提供するプログラムも多数あるため、ユーザーは自分のニーズに応じて、対応するバージョンを選択してインストールできます。32 ビット Windows システムの場合は 32 ビット インストール パッケージのみをインストールできますが、64 ビット Windows システムの場合は 32 ビットと 64 ビットのインストール パッケージの両方をインストールできます。

       開発者の観点からは、次の 2 つの点に注意してください。

1) システム内の 32 ビット プログラム プロセスと 64 ビット プログラム プロセスによって割り当てられる仮想メモリのサイズには大きな違いがあり、
        32 ビット プログラムの場合、システムは開始されたプログラムに 2 の 32 乗の仮想メモリを割り当てます。 、つまり4GBです。64 ビット プログラムの場合、システムは 2 の 64 乗の仮想メモリをプログラム プロセスに割り当てます。つまり、仮想メモリは非常に大きく、32 ビット プログラムの 4GB の仮想メモリよりもはるかに大きくなります。32 ビット プログラムの場合、ユーザー モード メモリは 2GB、カーネル モード メモリは 2GB です。大規模なソフトウェアの場合、動作中に大量のメモリ領域を占有し、仮想メモリが不足する可能性があります。仮想メモリが不足している場合は、十分ではない場合、メモリ不足のメモリ枯渇例外が発生します。以前にメモリ リークについて話したときに、このメモリ枯渇例外についても話しました。
2) ビット数の異なる Exe ライブラリと DLL ライブラリを混在させることはできません
       32 ビット プログラムで 64 ビット DLL ファイルを使用することはできません、64 ビット プログラムで 32 ビット DLL ファイルを使用することはできません ビット数が異なるため、アドレッシング範囲が異なります異なります。32 ビット プログラムでは 32 ビット DLL ファイルを使用する必要があり、64 ビット プログラムでは 64 ビット DLL ファイルを使用する必要があります。そのため、VLD では 32 ビットと 64 ビットの 2 つのバージョンのライブラリが提供されており、ユーザーはプログラムのビット数に応じて対応するバージョンを選択できます。

4. プロジェクトに VLD を導入する

       Visual Leak Detector は、直接実行できるツールとは異なる exe 実行可能プログラムではなく、コードに統合し、コードを再コンパイルして、プログラムの実行中に検出する必要がある DLL 動的ライブラリです。

       VLD を参照するときは、通常の DLL ライブラリを参照するのと同じように、最初にライブラリのヘッダー ファイル (vld.h) をインクルードし、次にライブラリの .lib ファイル (vld.lib、コンパイルおよびリンク時に必要) を導入してから、 dll ファイルを exe メイン プログラムのディレクトリにコピーします。

1) vld.h ヘッダー ファイルをインクルードします (コンパイル用)

       vld.h ヘッダー ファイルをインクルードする前に、vld.h ヘッダー ファイルのパスをプロジェクト プロパティに設定する必要があります: C/C++ -> 一般、追加のインクルード ディレクトリに vld.h ヘッダー ファイルのパスを追加します。以下に示すように:

このようにして、コードをコンパイルするときに、上記のパスに移動して vld.h ヘッダー ファイルを見つけます。

2) vld.lib ファイルを導入します (リンク用)

       vld.lib ファイルを導入する前に、プロジェクト プロパティで vld.lib ファイルが存在するパスを設定する必要があります。 [リンカー] -> [全般] で、vld.lib ファイルが存在するパスを追加のライブラリ ディレクトリに追加します。以下に続きます:

このようにして、コンパイルおよびリンクすると、vld.lib ファイルが上記のパスで検索され、リンクされます。ここでは、次に示すように、vld.h ヘッダー ファイルが自動的に導入されるため、vld.lib ファイルをプロジェクト コードに手動で導入する必要はありません。

3) vld.dll ライブラリ ファイルを exe メイン プログラム ディレクトリにコピーします (実行用)。

      インストール ディレクトリの bin フォルダーに移動し、dll とその他のファイルを exe メイン プログラムのディレクトリにコピーします。

      コードをコンパイルし、プログラムを実行して、検出結果を表示します。

5. メモリリーク検出の説明例

         以前に win32 コンソール プロジェクト TestMemLeak を作成し、次に示すように main 関数でメモリを動的に適用するコード行を追加しました。

main 関数が終了するとき、VLD の検出効果をテストするために、メモリは意図的に解放されません。

5.1. プログラム起動時のエラー

       前述のように、ヘッダー ファイルと .lib ファイルのパスをプロジェクトに設定し、vld.h ヘッダー ファイルをインクルードします。コードをコンパイルしてデバッグを開始すると、開始時にエラーが発生し、次
のプロンプト ボックスが表示されます。

プログラムを開始できません。対応する例外コードは 0xc0150002 です。

        このエラー コードの意味を理解するには、VS でよく知られたエラー コード マクロSTATUS_STACK_OVERFLOW
を直接入力し、対応するシステム例外コードによって定義されたヘッダー ファイルに移動します。対応するパスは次のとおりです: C:\Program Files (x86) \ Microsoft SDKs\Windows\v7.0A\include\ntstatus.h は、
ヘッダー ファイル内で例外コード 0xc0150002 を検索しようとしましたが、次のように、予想どおりに例外コードが見つかりました。

システムはアプリケーションからのバインド情報を処理できません。bin ディレクトリ内のファイルをコピーするときに、vld_x86.dll だけでなく、ディレクトリ内の他のファイルもコピーする必要がある可能性はありますか?
そこで、bin ディレクトリにあるdbghelp.dllコピーし、exe プログラムを再実行したところ、エラーは報告されなくなりました。

5.2. デバッグを開始してメモリリークレポートを表示する

       main 関数は比較的単純なので、入力するとすぐに終了し、プログラムが終了します。次に、Visual Studio の出力ウィンドウに、次のように表示されました: Visual Leak Detector がメモリ リークを検出しました!、つまり、以下に示すように、VLD がメモリ リークを検出しました。

メモリ リークのアドレスとサイズを出力します。

---------- 0x01497020 のブロック 1: 1024 バイト ----------

同時に、リークしたコードが存在するスレッドの関数呼び出しスタックも出力され、リークしたメモリの内容が表示されます。画像内のコード行をダブルクリックすると、メモリ リークが発生しているコード行にジャンプします。

5.3. vld.ini 設定ファイルの使用

      以下に示すように、VLD インストール ディレクトリには vld.ini 構成ファイルもあります。

VLD の一部の設定はこの設定ファイルで行うことができますが、このファイルを使用する場合は、exe メイン プログラムのディレクトリにコピーする必要があります。

       ReportTo 設定項目を使用できます。デフォルトでは、分析レポートは次のようにデバッガー ウィンドウに出力されます。

両方に設定することができ、デバッガウィンドウに出力したり、検出レポートをファイルに出力したりすることができます。ReportTo オプションが両方に設定されている場合は、次のように ReportFile オプションも設定して、エクスポート先のファイル名を指定する必要があります。

他にも設定オプションがあり、ファイルには詳細な注釈が記載されているので、興味がある場合は自分で試してみてください。

6. 最後に

       Windbg の umdh プログラムを使用してメモリ リークを検出することもできます。私たちはこれをプロジェクトで使用しており、その効果は良好です。umdh を使用してメモリ リークを検出する詳細なプロセスについては、以前に書いた記事を参照してください: Windbg を使用
して Windows C++ プログラムのメモリ リークを特定するicon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/121295720 umdh 分析、不要 コードを再コンパイルする方が便利です。VLDを使用する場合はコードを再コンパイルする必要があり、さらに面倒です。特に大規模なソフトウェアの場合、ソフトウェアには複数の dll モジュールが含まれており、異なる dll モジュールは異なる開発グループによって保守されており、すべてのモジュールを VLD で再コンパイルすることは容易ではなく、全体的な調整が必要であり、容易な作業ではありません。

       さらに、これらのメモリ リーク検出ツールは万能ではなく、すべてのシナリオでリークを検出できるわけではありません。大規模なソフトウェアには複数のモジュールが含まれるため、コードが煩雑で複雑になります。一部のモジュールは起動するとすぐにメモリを適用し、決して解放されません。一部のモジュールはメモリ プールを使用する場合があり、メモリ管理がより複雑になります。これはツールによる誤検出につながるため、実際のメモリリークポイントであるかどうかは、具体的なコードとビジネスに基づいて分析する必要があります。1 つのツールで検出できない場合は、他のツール、場合によっては多数のツールを試す必要があります。

       メモリリークを解析するツールとしては、数年前にはBoundsCheckerという強力なツールがありましたが、このツールは長い間メンテナンスされておらず、新しいバージョンのVisual Studioは使用できなくなりました。さらに、Visual Studio 2019 V19.6 では、Google のメモリ分析ツール AddressSanitizer が導入されました。

AddressSanitizer も試してください。VS で AddressSanitizer メモリ分析ツールを使用する方法については、Microsoft の公式記事で詳細な手順を読むことができます。

Visual Studio での AddressSanitizer の使用icon-default.png?t=N7T8https://docs.microsoft.com/zh-cn/cpp/sanitizers/asan?view=msvc-170        Visual Studio に統合された AddressSanitizer を使用するには、IDE を Visual Studio 2019 V19 にアップグレードする必要があります。 6 以降では、大規模なソフトウェアの複数のモジュールを上から下まで特定のバージョンにアップグレードするには、ある程度の時間と人手がかかります。

おすすめ

転載: blog.csdn.net/chenlycly/article/details/133041372