VS2005でダイアログベースのテストアプリケーションを用意し、
ボタンクリックのハンドラの中に以下のようなテストルーチンを入れました。
void CAAAADlg::OnBnClickedButton1()
{
static int a = 10;
CClientDC dc(this);
LOGFONT logfont;
ZeroMemory(&logfont, sizeof(logfont));
logfont.lfHeight = a++;
logfont.lfCharSet = DEFAULT_CHARSET;
CFont font;
font.CreateFontIndirect(&logfont);
CFont* pFont = (CFont*)dc.SelectObject(&font);
dc.DrawText(_T(1), CRect(0, 0, 500, 500), 0);
dc.SelectObject(pFont);
font.DeleteObject();
}
ダイアログを表示させ、ボタン1上でEnterキーを押し続けると、
どんどん「1」の文字が大きくなっていきますが、
タスクマネージャ上のメモリ使用量もどんどん増えていきます。
なお、dc.DrawText()の部分をコメントアウトしたり、
フォントサイズ(a)を増やさずに同じ値のままにしておくと、
何度コールしても使用量は全く増えません。
なぜこららの関数を呼ぶだけでなぜ増えていくのでしょうか。
なにか解放し忘れているものがありますでしょうか?
描画が終わってないのに再び
「void CAAAADlg::OnBnClickedButton1()」
が呼ばれるからでは?
フラグを設定するかして、描画が終わるまで再び
処理を行わないようにしないと駄目ですね。
あと気になったので、
> static int a = 10;
staticを使わずにメンバー変数を使ったほうがいいのでは?
> logfont.lfHeight = a++;
どんどん増えてしまうよ......
if(a > ??) a = 0; ??は任意の値
等がいるのではないでしょうか?
void CAAAADlg::OnBnClickedButton1()
{
static int a = 10;
CClientDC dc(this);
int id = dc.SaveDC() ;//ここ
LOGFONT logfont;
ZeroMemory(&logfont, sizeof(logfont));
logfont.lfHeight = a++;
logfont.lfCharSet = DEFAULT_CHARSET;
CFont font;
font.CreateFontIndirect(&logfont);
CFont* pFont = (CFont*)dc.SelectObject(&font);
dc.DrawText(_T(1), CRect(0, 0, 500, 500), 0);
dc.SelectObject(pFont);//問題はここでしょ
dc.RestorDC( id ) ; //ここについか
font.DeleteObject();
ごめんちがったw
忘れてくださいw
> 描画が終わってないのに再び
> 「void CAAAADlg::OnBnClickedButton1()」
> が呼ばれるからでは?
Windowsのメッセージループ上、OnBnClickedButton1を抜けるまでは
再びOnBnClickedButton1に来ることは無いはずです。
実際、適当なタイミングでゆっくりとクリックし続けても
メモリ使用量は増え続けていきます。
なお、この現象はXP上で発生していたのですが、
さきほど同じプログラムを2000で試してみたところ、
メモリ使用量が増えることはありませんでした。
また、DrawTextの部分を
dc.TextOut(0, 0, _T(1));
とすると、XPでもメモリ使用量は増えませんでした。
XPのDrawTextって、なにか制限でもあるのでしょうか。
> staticを使わずにメンバー変数を使ったほうがいいのでは?
> どんどん増えてしまうよ......
もちろん、これはプロジェクト名からもわかるとおり、
一時的に用意したテストプログラムです。
別の本番プログラムでメモリ使用量が増え続ける問題があり、
いろいろ原因を探っていたところDrawTextの部分が怪しいことがわかり、
その部分だけに絞ってテストプログラムを作ってみたら同じ現象が出たため、
ここで質問させていただきました。
興味があり、少し検証してみました。
当方でも再現できました。
logfont.lfHeight = 20/*a++*/;
と20固定で実行すると全く増えませんね。
なんでしょうねぇ。
当然こんなことしても増える一方。
//デバッグ中にm_Dirを反転する
if(m_Dir){
logfont.lfHeight = a++;
}else{
logfont.lfHeight = a--;
}
パフォーマンスで観察するとPrivateBytes、
VirtualBytesがうなぎ登り・・・。
> 別の本番プログラムでメモリ使用量が増え続ける問題があり、
> いろいろ原因を探っていたところDrawTextの部分が怪しいことがわかり、
> その部分だけに絞ってテストプログラムを作ってみたら同じ現象が出たため、
VC++2003, XPでも再現しました。
if (++a > 200) a = 10;
このようにして、タイマーで呼び出してみましたが、
メモリ使用量は一定の値以上には増えませんでした。
おそらく、フォントがキャッシュされているようなイメージだと思うのですが。
解放漏れではないと思いますので、そういうものだと割り切るのが楽ですが、
本番プログラムで、どのような不都合がありますか?
ありえないくらい多くのフォントを使うとか?
試していただき、ありがとうございます。
サイズをいじらないと増えないということは、
XPでは一度使ったフォントをOSがキャッシュしているのかなとも思うのですが、
このテストプログラムでEnterを押し続けていると、
平気でメモリ使用量が1GBとか超えていきます。
本番ではグラフィックエディタのようなものを作っており、
表示倍率の拡大縮小などを繰り返したりフォントを変更したりすると、
メモリ使用量がどんどん増えていくのです。
たしかに、OS自体がこの状態でも問題無く動いてくれるのならよいのですが、
これは正常な動きと報告してしまってもよいものなのでしょうか…。
> たしかに、OS自体がこの状態でも問題無く動いてくれるのならよいのですが、
> これは正常な動きと報告してしまってもよいものなのでしょうか…。
怖いですね。
ちなみに、CView::OnDrawで同じようなコードを書いても再現しませんでした。
私では原因不明。私にできることはSDKで試すことと他の回答を待つ位か。