HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0823
とあるプログラマGetDCでメモリリーク6解決


とあるプログラマ

リンク

2020/8/23(Sun) 18:17:03|NO.91245

HSP3でGetDC関数を実行するとどうやらメモリリーク?しているようです。

以下検証用コードですが注意事項を。
・タスクマネージャーを起動した状態で実行してください。もし問題が起きたときにすぐにHSP3を終了させるためです。
・メモリ使用量の変化を確認したらすぐにプログラムを終了してください。長時間起動し続けるとPCの動作に影響してきます。
・コード中にもコメントしてありますが、awaitで10未満(=待機時間10ms以下)にしないでください。PCがとても重くなり、最悪の場合ブルスク案件になりかねません。


#include "user32.as" repeat dim dc dc = GetDC(hwnd) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% wait 1 //絶対に await 1にしないこと!!!!! //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% loop

タスクマネージャーの詳細タブだと分かりやすいですが、更新されるたびにどんどんメモリ使用量が増えていくのが分かります。
別のコードでK32GetProcessMemoryInfoGetDCを使い調べたところ、GetDCを実行するたびに4バイトのメモリ使用量の増加が確認できます。

すなわちGetDC関数毎にint型のメモリリークが発生していると思われます。
その他の関数(GetDesktopWindowやWindowFromPointなど)ではメモリの増加は確認されませんでした。
その他のデバイスコンテキストを扱う関数(CreateCompatibleDC、CreateCompatibleBitmap)などでもメモリの増加は確認されませんでした。
それ以外の関数でもメモリリークが起きている可能性はありますが関数ごとに検証してみないことには分かりかねます。

またhsp3.5〜3.6beta3の各環境で検証してみたところどの環境でも起こりました。


なぜGetDCだけなのかは分かりませんが、メモリリークはかなり重大な問題だと思います。(コーディングユーザがReleaseDCなどを忘れてる等ならまだしも言語側の問題となると)

HSP3側の問題であればなるべく早急に対応していただきたいです。
もし何か一時的な回避策があればご教授いただければ幸いです。



この記事に返信する


MillkeyStars

リンク

2020/8/23(Sun) 18:49:09|NO.91246

GetDC は、デバイスコンテキストを対象ウィンドウの初期化情報を用いて作成する物です。
GetDC は ReleaseDC と対で使用するものであり、一方だけを使用するものではありません。

4バイト増えるのは仕様です。GetDC の戻り値がハンドル(32bit値)であるので増えていきます。
ReleaseDC を行うと減っていきます。

なにを行いたいのかわかりませんが、GetDC はその都度取得するものではありませんので、ループ内で同じウィンドウを対象とした GetDC はおやめください。
GetDC の引数が指定されない場合、NULL = デスクトップのDC を取得する事になります。



MillkeyStars

リンク

2020/8/23(Sun) 18:55:30|NO.91247

追記です。
#include "user32.as" は、WinAPI (Windows ダイナミックリンクライブラリ)への定義ファイルであり、HSP のシステムとは関係ありません。
その他にも、"kernel32.as"・"gdi32.as"・"ole32.as"などがあります。



X

リンク

2020/8/23(Sun) 19:20:59|NO.91248

これで何となく感じが掴めるかと思いますがいかがでしょうか


#uselib "user32.dll" #cfunc GetDC "GetDC" int #func ReleaseDC "ReleaseDC" int, int #uselib "gdi32.dll" #func TextOut "TextOutA" int, int, int, str, int onexit goto *OnAppQuit HSPHWND = hwnd posx = 100 posy = 200 string = "HSP" strlength = strlen(string) repeat dc = GetDC(HSPHWND)//ハンドルを取得 TextOut dc, posx, posy, string, strlength//ここで描画 await 1 ReleaseDC HSPHWND, dc//ハンドルを解放 loop *OnAppQuit end

同じハンドルを使いまわすのであればloop外で取得開放が良いかと思われます。



とあるプログラマ

リンク

2020/8/23(Sun) 20:01:55|NO.91249

お二方ありがとうございます。

GetDCは呼出し後に必ずReleaseDCをする必要があったのですね…
GetDCがuser32の関数でReleaseDCがgdi32の関数なので勝手に関連性はないと判断していました。

これに関しては完全に自分の落ち度です。
勘違いで余計なスレを立ててしまい申し訳ありません。



とあるプログラマ

リンク

2020/8/23(Sun) 20:53:29|NO.91250

すみません、ReleaseDCはuser32でしたね… DeleteDCと混同してました。

ちょっと今日は調子悪いようなのでこの件はこれにて失礼いたします。本当に申し訳ございません。



リンク

2020/8/24(Mon) 12:39:31|NO.91254

こんな基本的なことを知らないでAPI弄ってるって危なくない?



ONION software Copyright 1997-2023(c) All rights reserved.