リード開発メモ

大阪のソフトウェア会社です。 技術的な事柄についてのメモとしてブログを始めます。

Windows

VC++ メモリリークの検出(その2)

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 などに以下を記載する。
#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 関数のように問題の場所を特定するための手間が不要なのがいい。

ただし、処理速度は恐ろしく遅い。そのため、常時使うというよりはメモリリークを調べるときだけ、プロジェクトの設定を変えることになりそう。

以上。

タスクトレイの「Windows 10 を入手する」アイコンを消す

タスクトレイに表示されている「Windows 10 を入手する」アイコンを消す。Windows 7 でのやり方です。

BlockWindows10Update0

コントロールパネルから「プログラムのアンインストール」を選び、左の「インストールされた更新プログラムを表示」をクリック。

BlockWindows10Update6


ウィンドウ右上の検索窓に「KB3035583」と入力。これがタスクトレイに例のアイコンを表示した更新プログラムである。

BlockWindows10Update7

これをアンインストールする。再起動を促されるので、再起動する。
するとタスクトレイのアイコンが消えている。

BlockWindows10Update10


ただし、このままだとWindows Updateのとき再度「KB3035583」がインストールされてしまうので、それを防ぐために、Windows Updateの対象から外しておく必要がある。

再度、コントロールパネルを開き、
    「システムとセキュリティ」-「Windows Update」-「更新プログラムの確認」
を選ぶ。
表示された更新プログラムの中から、「KB3035583」を見つける。チェックが入っているはずだ。
右クリックし、「更新プログラムの非表示」を実行する。

BlockWindows10Update11


するとチェックが外れ、これで問題の「KB3035583」は自動でインストールされなくなる。

以上です。

VC++ メモリリークの検出

Visual C++ でメモリリークを検出する方法。

main 関数の出口で _CrtDumpMemoryLeaks 関数を呼ぶことによって、メモリリークを検出できる。ただ、下のようにあらかじめ_CrtSetDbgFlag で設定しておくことにより、プログラムがどのような終了の仕方をしても_CrtDumpMemoryLeaks 関数を呼んでくれるので、そのほうがよさそう。
// LeakTest1.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

#if WIN32
#include 
#define _CRTDBG_MAP_ALLOC
#ifdef _DEBUG
#define new  ::new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#endif

int _tmain(int argc, _TCHAR* argv[])
{
#if WIN32
	// デバッグウィンドウに出力
	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	//_CrtSetBreakAlloc(146);	// ブレークさせたいとき用
#endif

	// わざとメモリーリークさせる
	char* p1 = new char[5];
	int* p2 = new int[3];

	return 0;
}

実行結果は以下のとおり。上のサンプルだと出力先は出力ウィンドウとなっているが、ファイルやウィンドウに出力させることもできる。
Detected memory leaks!
Dumping objects ->
c:\work\leaktest1\leaktest1.cpp(27) : {147} normal block at 0x0072EC70, 12 bytes long.
 Data: <            > CD CD CD CD CD CD CD CD CD CD CD CD 
c:\work\leaktest1\leaktest1.cpp(26) : {146} normal block at 0x0072EC28, 5 bytes long.
 Data: <     > CD CD CD CD CD 
Object dump complete.

以上。

Windows リモートデスクトップで大きなファイルを転送する

リモートデスクトップでは、コピー&ペーストで接続先のマシンとの間でファイルをコピーすることができるが、その間リモートデスクトップは操作不能になってしまう。

ある程度大きなファイルを転送する場合は、で接続先のマシンとの間でドライブを共有して、ファイルをコピーするといい。

手順は以下のとおり。

接続する前に、リモートデスクトップ接続ダイアログで[オプション]を開く。
remote-desktop-localdrive1

[ローカル リソース]タブを選び、[ローカル デバイスとリソース]の[詳細]を選ぶ。
remote-desktop-localdrive2

[ドライブ]にチェックを入れ、[OK]を押す。
remote-desktop-localdrive3

以上の設定を行ったあと、リモートデスクトップ接続を行うと、接続先のマシンのドライブとして、接続元のマシンのドライブが現れる。これで接続先のマシンとの間で、ファイルの操作がエクスプローラー上で行えるようになる。

以上。

Windows 7 でノートPCのふたを閉じてもスリープしないようにする

Windows 7 でノートPCのふたを閉じてもスリープしないようにする設定方法。

1. コントロールパネルより[電源オプション]を選ぶ。
2. [コンピューターがスリープ状態になる時間を変更を変更]を選ぶ。
3. [詳細な電源設定の変更]を選ぶ。
4. [電源ボタンとカバー]の[カバーを閉じたときの操作]を開き、
  [スリープ状態]になっているのを[何もしない]に変更する。
5. [OK] ボタンを押す。

no-sleep

以上。

アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

livedoor 天気