VC++ でメモリリークを検出する方法として、これまで _CrtDumpMemoryLeaks 関数を使っていた。
VC++ メモリリークの検出
ただ、これだと OpenCV や Qt といったライブラリ側でのどうしようもないメモリリークまで拾ってしまい、非常に困っていた。
そこで別の方法としてVisual Leak Detectorを試してみる。
以下よりダウンロードして、インストールする。
Visual Leak Detector for Visual C++ 2008-2015
VC++ プロジェクトのプロパティから以下を設定する。
[C/C++] -[全般] - [追加のインクルードディレクトリ]に以下を追加。
C:\Program Files (x86)\Visual Leak Detector\include
[リンカー] - [全般] - [追加のライブラリディレクトリ]に以下を追加。
ビルド構成が Win32 の場合
C:\Program Files (x86)\Visual Leak Detector\lib\Win32
ビルド構成が x64 の場合
C:\Program Files (x86)\Visual Leak Detector\lib\Win64
[リンカー] - [入力] - [追加の依存ファイル]に以下を追加。
vld.lib
リンクは、#pragma comment(lib, xxxx) の方法ではビルドができなかった。
最後に、プログラムのいずれかの cpp ファイル、たとえば main.cpp などに以下を記載する。
あとはビルドして実行するだけ。
終了時、出力ウィンドウにメモリリークの状況が出力される。
OpenCV や Qt といったライブラリ側でのメモリリークは検知しなかった。モノによってはするかもしれないが。
メモリリークがないときはこのように出力される。
メモリリークがあるときはこう。
上のほうに、「editwindow.cpp (42)」とあるが、これがばっちり今回メモリリークの原因となったnewの位置を示していた。_CrtDumpMemoryLeaks 関数のように問題の場所を特定するための手間が不要なのがいい。
ただし、処理速度は恐ろしく遅い。そのため、常時使うというよりはメモリリークを調べるときだけ、プロジェクトの設定を変えることになりそう。
以上。
ただ、これだと OpenCV や Qt といったライブラリ側でのどうしようもないメモリリークまで拾ってしまい、非常に困っていた。
そこで別の方法としてVisual Leak Detectorを試してみる。
以下よりダウンロードして、インストールする。
Visual Leak Detector for Visual C++ 2008-2015
VC++ プロジェクトのプロパティから以下を設定する。
[C/C++] -[全般] - [追加のインクルードディレクトリ]に以下を追加。
C:\Program Files (x86)\Visual Leak Detector\include
[リンカー] - [全般] - [追加のライブラリディレクトリ]に以下を追加。
ビルド構成が Win32 の場合
C:\Program Files (x86)\Visual Leak Detector\lib\Win32
ビルド構成が x64 の場合
C:\Program Files (x86)\Visual Leak Detector\lib\Win64
[リンカー] - [入力] - [追加の依存ファイル]に以下を追加。
vld.lib
リンクは、#pragma comment(lib, xxxx) の方法ではビルドができなかった。
最後に、プログラムのいずれかの cpp ファイル、たとえば main.cpp などに以下を記載する。
#include <vld.h>
あとはビルドして実行するだけ。
終了時、出力ウィンドウにメモリリークの状況が出力される。
OpenCV や Qt といったライブラリ側でのメモリリークは検知しなかった。モノによってはするかもしれないが。
メモリリークがないときはこのように出力される。
No memory leaks detected. Visual Leak Detector is now exiting.
メモリリークがあるときはこう。
WARNING: Visual Leak Detector detected memory leaks! ---------- Block 281 at 0x088800B0: 320 bytes ---------- Leak Hash: 0x46FC2A4A, Count: 1, Total 320 bytes Call Stack (TID 6024): MSVCR120D.dll!operator new() c:\work\src\movieeditor\movieeditor\movieeditor\editwindow.cpp (42): MovieEditor.exe!EditWindow::EditWindow() + 0xA bytes c:\work\src\movieeditor\movieeditor\movieeditor\mainwindow.cpp (1032): MovieEditor.exe!MainWindow::editButton_clicked() + 0x27 bytes c:\work\src\movieeditor\movieeditor\movieeditor\generatedfiles\debug\moc_mainwindow.cpp (185): MovieEditor.exe!MainWindow::qt_static_metacall() + 0x8 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x30C5F4 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x30C03C bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x4E73FB bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x184F67 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x1844EB bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x183912 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x7E0FD bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x183471 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x244A1B bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x33AAE bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x3053B bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x2CA892 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x3E9A43 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x35813 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0xB2743 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0xB17F8 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x33AAE bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x2FECE bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x2CA892 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x3E9A43 bytes Qt5Guid.dll!QPainter::drawImage() + 0x61D85 bytes Qt5Guid.dll!QPainter::drawImage() + 0x63DB9 bytes Qt5Guid.dll!QPainter::drawImage() + 0x38901 bytes qwindowsd.dll!qt_plugin_query_metadata() + 0x40295 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x35AFFB bytes USER32.dll!SetManipulationInputTarget() + 0x53 bytes USER32.dll!CallWindowProcW() + 0x300 bytes USER32.dll!DispatchMessageW() + 0x251 bytes USER32.dll!DispatchMessageW() + 0x10 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x35BB49 bytes qwindowsd.dll!qt_plugin_query_metadata() + 0x401B0 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x2C65F7 bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x2C67FD bytes Qt5Cored.dll!QSortFilterProxyModel::mapToSource() + 0x2C8EBD bytes Qt5Guid.dll!QPainter::drawImage() + 0x606C8 bytes Qt5Widgetsd.dll!QAbstractScrollArea::setHorizontalScrollBar() + 0x2FB29 bytes c:\work\src\movieeditor\movieeditor\movieeditor\main.cpp (56): MovieEditor.exe!main() + 0x6 bytes c:\work\build\qt5_workdir\w\s\qtbase\src\winmain\qtmain_win.cpp (113): MovieEditor.exe!WinMain() + 0xD bytes f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): MovieEditor.exe!WinMainCRTStartup() KERNEL32.DLL!BaseThreadInitThunk() + 0x24 bytes ntdll.dll!RtlUnicodeStringToInteger() + 0x253 bytes ntdll.dll!RtlUnicodeStringToInteger() + 0x21E bytes Data: 00 00 00 00 00 00 00 00 00 00 00 00 80 E1 F9 57 ........ .......W 00 00 CD CD 00 00 00 00 20 28 88 08 80 E1 F9 57 ........ .(.....W 00 00 CD CD 00 00 00 00 D0 04 97 08 80 E1 F9 57 ........ .......W 00 00 CD CD 00 00 00 00 60 7F 8F 05 80 E1 F9 57 ........ `......W 00 00 CD CD 00 00 00 00 50 30 A7 08 80 E1 F9 57 ........ P0.....W 00 00 CD CD 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ 00 00 00 00 CD CC CC 3E 01 00 00 00 FF FF FF FF .......> ........ 00 00 FF FF 00 00 CD CD 70 00 9E 05 80 02 00 00 ........ p....... 68 01 00 00 90 C0 93 05 7F 03 00 00 88 06 90 05 h....... ........ 80 52 79 05 C0 B9 79 05 30 42 8B 05 B0 7F A2 08 .Ry...y. 0B...... B0 8D 9F 08 48 94 57 57 48 94 57 57 FF FF FF FF ....H.WW H.WW.... FF FF FF FF 00 CD CD CD 48 94 57 57 E0 FE 9D 05 ........ H.WW.... 01 CD CD CD 68 94 57 57 90 ED 90 05 88 0A 9E 05 ....h.WW ........ 20 0C 9E 05 E0 6F 8B 08 88 84 92 05 00 00 CD CD .....o.. ........ B8 FB 9D 05 68 7F 70 00 00 00 00 00 00 00 00 00 ....h.p. ........ FF FF 00 00 00 00 00 00 00 00 CD CD 68 94 57 57 ........ ....h.WW Visual Leak Detector detected 1 memory leak (356 bytes). Largest number used: 4858632 bytes. Total allocations: 18686028 bytes. Visual Leak Detector is now exiting.
上のほうに、「editwindow.cpp (42)」とあるが、これがばっちり今回メモリリークの原因となったnewの位置を示していた。_CrtDumpMemoryLeaks 関数のように問題の場所を特定するための手間が不要なのがいい。
ただし、処理速度は恐ろしく遅い。そのため、常時使うというよりはメモリリークを調べるときだけ、プロジェクトの設定を変えることになりそう。
以上。