忘れる前に覚書。優しい文章を目指します。
ザ・覚書 ザ・覚書
出来るだけ子供にも、わかりやすいように書いて行きたいと思います。

PCバージョンでサイトを表示しています。
【ザ・覚書 3クリックアンケート実施中】
暑さの一番の原因はなんだと思いますか?
あなたの支持する政党はどの党ですか?

メモリリーク GDI関連のチェック方法

☆メモリリーク GDI関連のチェック方法
今のページの関連ページのリストへ
ザ・覚書のトップページに戻る

別にCとは限らないんですが、
デバイスコンテキストを使うアプリを作っていて、いつものメモリリーク(解放忘れなど)
とは違うリーク忘れがあって、見つけるのに苦労したので覚書しておきます。

まずそれを発見する方法ですが、通常のメモリークなら、
タスクマネージャーのメモリの残量をアプリを操作しながら見て入れば大体わかるのですが、
デバイスコンテキスト周りの場合、GDIオブジェクトというのをみないといけないようで、
Winodws8のタスクマネージャーではどこにもなさそうです。
WinodwsXPにはあった。

そこで、フリーソフトの「ProcessExplorer」というので
(初期状態ではGDIオブジェクトはないので)、「View」メニュー→「Select Columns」→「Process Memory」タブで
GDIオブジェクトを表示させます。

アプリをデバッグなどで動かしたら、EXE名が現れるので、そこのGDIオブジェクトを見ながら操作します。
(通常のメモリリークもタスクマネージャーでみたりします。)

リークしている場合、
ここで公開したような小さいアプリならわかりにくいかも知れませんし、
複雑な事はしないので、アプリを閉じてしまえば最悪は良いんですけど、
色々する複雑な事をする比較的大きいアプリだと
(それが意図した確保とかなら良いのですが)
値が増えて、リークの場合はするごとに
そのリークした増えた分の値は戻る事はないので
スペックの良くないパソコンだと固まります。
で、保存機能があるなら保存していないと、それまでの作業が全部パァーになってしまったりします。


アプリの推奨スペックより遅いものならハード的に無理なところもあって、
そこでリークなしで作っていて動かないのは当然ですが、
推奨スペックを満たしたパソコンなら、トロトロしながらも
動いていかないと駄目となるでしょう。
リークはできるだけなくさないと駄目になります。

以下に一応、失敗例も書いておきます。






・その失敗の例


直してしまって、いまいちどこだか覚えていませんが、多分この辺だったというのを書いておきます。
過去のソースも残っていますが、どこだか忘れぎみ。


①WM_PAINT辺り等の描画系で、

SelectObject(hmemdc , CreateSolidBrush(RGB(0xFF , 0xFF , 0xFF)));  

こんな事をしていた。
で、hmemdcの解放はアプリ終了時とかにしていた。


裏デバイスコンテキスト(この場合、hmemdc)として使っていたんですが、
この裏デバイスコンテキストが解放されないと、
CreateSolidBrushは解放されないので、WM_PAINT毎にどんどん増えていく。

なので、アプリ開始時にCreateSolidBrushを1回だけする事で解決。

どこかで1回だけ、HBRUSH hbrush;とかにCreateSolidBrushをして
SelectObject(hmemdc , hbrush);
とかにする。


②これもWM_PAINT辺り等の描画系で、
hPen = CreatePen(PS_DOT, 1, RGB(100, 100, 100));
hOldPen = SelectObject(hmemdc, hPen);
なんか処理
DeleteObject(hPen);
こんな感じ。

これも裏デバイスコンテキスト(この場合、hmemdc)として使っていたんですが、
DeleteObjectしているのに、この裏デバイスコンテキストが解放されないと、
hPenは解放されないので、WM_PAINT毎にどんどん増えていく。

なので、アプリ開始時にCreatePenを1回だけする事で解決。

どこかで1回だけ、HPEN hPen;とかにCreatePenをして
SelectObject(hmemdc, hPen);
とかにする。

③もういらない作業用のデバイスコンテキストの解放忘れ。



・その他の失敗


デバイスコンテキストとは関係ないですが、わかりにくかったのを覚書しておきます。

処理の一部部分をサンプルから頂いて来て、
クラスで、NewしたのをDeleteしていなかった。
それに気が付くまで、ファイルを掴んだままで、リーク。


GDI+で、
Gdiplus::Bitmap* pImage;
Bitmap pImage(wszFileName);
とか書かれていたので、見逃してしまい。

省略せずちゃんと書いて、
Gdiplus::Bitmap* pImage;
Bitmap* pImage = new Bitmap(wszFileName);
などにしてちゃんとdelete(pImage);



ここも気が付かず直すのに苦労しました。
短縮で書くプログラムは気づきにくいので、
多少文字列が長くなろうが、できるだけちゃんと書いた方が良いのかも知れません。


・感想など


多分、この辺でミスっていたんだったと思います。
わかれば簡単な事ですが、見つけるまで時間が掛ったりします。

適当にプログラムしてしまうと、リーク対応が一番めんどくさいのですが、
ああでもないこうでもない、ここと仮定して深く見るとかなど、
知恵熱出すぐらい脳を使う事もあり、これはこれで面白く感じてしまいます。
対処出来てスムーズに動いた時の満足感がまた良いです。

初めからキッチリ書けば良いんですが。
仕事とかなら自分で一から書けずに、改修とかもありますから、
こういうのも気にしていると良いかも知れません。


ボケ防止に自分専用のアプリをプログラミングするのも良いかも知れません。


記述:2014年09月頃





Twitter Facebook Google+ はてな Pocket LINE




一言掲示板です。なにかありましたら以下に書いて書き込みボタンを押して下さい。
管理人による書き込みの確認後、荒らし書き込みでない場合に表示させていただきます。
悪意ある書き込みや挑発的な書き込みと思われる内容は、表示させません。
その為、ちょっと書き込みから表示までに時間がかかってしまいます。ご了承下さい。

お名前

コメント




ファイル関連
C言語 ファイルオープン・クローズ
乱数
C言語 乱数発生関数例
Bitで遊ぶ
C言語 1バイトの数値内の何ビット目に1があるか返す関数例
C言語 1バイトの数値内の指定ビットの値を返す関数例
C言語 1バイトの数値内の指定ビットの値を1にする関数例
C言語 1バイトの数値内の指定ビットの値を0にする関数例
C言語 1バイトにいろいろな状態を入れてみる例
文字列操作
C言語 整数値を文字列に変換する関数例
C言語 ”ダブルコーテーションを文字列として扱う場合
C言語 CSVファイル形式のファイル内容を読み込む関数例
C言語 strtokでは連続トークンを正しく読み込まない
VisualC
C言語 とにかく自力でウィンドウ
C言語 UTF-8のファイル操作
その他
メモリリーク GDI関連のチェック方法
作ってみたアプリ
BMPの部分保存をするアプリ「ビットマップファイル部分取得」
16進数を自動加算してテキスト出力するアプリ
テキストファイル(txt)を字幕ファイル(srt)に変換するアプリ
C#
C# ファイルオープン・1行ずつ読み込み・書き込み・クローズ
C#のEXEは、中のソースコードのロジックを簡単に見られてしまうかも知れない
【ザ・覚書 3クリックアンケート実施中】
暑さの一番の原因はなんだと思いますか?
あなたの支持する政党はどの党ですか?

今のページの関連ページのリストへ
ザ・覚書のトップページに戻る
全ページのリストへ