リアルタイム表示リストボックスのメモリ節約?初期化? – プログラミング – Home

リアルタイム表示リストボックスのメモリ...
 
通知
すべてクリア

[解決済] リアルタイム表示リストボックスのメモリ節約?初期化?


はたやん
 はたやん
(@はたやん)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

はじめまして、よく過去ログを参考にさせていただいています。

VC++6.0 MFC
Win2000

まだまだペーペーなので間違っているかも知れませんが、
・リストボックス表示限界はメモリの許容する範囲
ですよね?

現在開発しているモノは実行状況及び、実行結果ログ
をリストボックスにて適時出力しています。
問題になっているのは表示が10000件を超えたあたりから
表示が壊れる(他のウィンドウにも影響有り)のです。
例: まったく関係の無い個所にスクロールバーがいきなり表示される。
その後異常終了する。

試しに1000毎にResetContentを発行してみたのですが、
結果は同一で、やはりウインドウが壊れるのです。
そして、メモリまでは開放されているように見えませんでした。
(タスクマネージャ上で確認)
リストボックスの内部ではどのようにメモリ管理を
行っているのでしょうか?
また、どのようにしてリストボックスが確保した領域を
開放するのでしょうか?

もしかして、表示件数が不定でかつ、大量の場合はリストボックスを
使用するべきではないのでしょうか?


引用未解決
トピックタグ
sugar
 sugar
(@sugar)
ゲスト
結合: 24年前
投稿: 448
 

ごめんなさい、内部の管理方法までは知らないのですが、
単純に思ったことがありまして。

このリストボックス、どんな用途なんですかね。
リストの中からユーザがひとつ選ぶためのものだとしたら、
数千件?数万件?の候補の中から選ばせるというのは・・・(汗
あまり使い手にとって優しいアプリとは言えませんよね。

何か条件をもって、候補を絞り込ませる仕様を入れれば、
最大件数問題も回避できるような気がしまして。


返信引用
はたやん
 はたやん
(@はたやん)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

レスありがとうございます。

確かに数万件の候補の中から選ばせるというのは
リストボックスの本来の用途とは外れていますね。
今回の満たしたい用途としては

・ログ、作業状況のリアルタイム表示
・水平、垂直スクロールバーの実装

なのです。
リスト内より選択する機能は必要ありません。
単純に表示がしたかったのです。
今回、リストボックスを使った意図は恥ずかしながらありません(汗
ですが、他のコントロールでも同じような問題が発生しそうな
気がしています。(n件のデータを表示するための領域の確保、開放)

最大件数の問題は「ある程度の目安を設けて表示を初期化」
で解決するのですが、ResetContentではメモリは開放しないようでした。
VBでのリストボックスで同じような処理をした場合、開放しているので
必ずメモリ開放のインタフェースはあると思うのですが...


返信引用
渋木宏明(ひどり)
 渋木宏明(ひどり)
(@渋木宏明(ひどり))
ゲスト
結合: 22年前
投稿: 196
 

リストボックスは Windows 3.1 時代から存在するコントロールなので、無茶な利用には
耐えません。

メモリ管理も内部に完全に隠蔽されているので、外部から救援の手を差し伸べることも
ままなりません。限界を超えるといきなり破綻してしまいます。

リストビューコントロールなら「仮想リスト」という技術を使うことで、アイテムが数
万件あっても、アプリケーション側の実装次第で破綻することなく表示が可能です。
(使いやすいかどうかは別として)

「仮想リスト」については、MSDN Library で解説されているので、まずはそれを参照し
てみてください。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

普通にResetContentすればリストボックスが使っているメモリは
解放されると思いますけど。
なにか付随するデータのメモリの解放漏れということはないでしょうか。

たとえば、リストボックスに10000件追加するだけのプログラム、
リストボックスに追加する処理を省略したプログラム、
などと比較してみてはどうでしょう。


返信引用
たみあ
 たみあ
(@たみあ)
ゲスト
結合: 22年前
投稿: 57
 

渡している文字列に、本来、そのコード体系にはないコードが
まざりこんでいる可能性はないですか?

NT系であれば、内部でUnicodeに変換して格納してと
ややこしそうなことをやっているはずですから
本来あってはいけないコードがまざっていると
メモリ管理が破綻する可能性が、、、すこしはあるかもしれません

ちなみに

>・リストボックス表示限界はメモリの許容する範囲

リソースの許容する範囲、だと思います


返信引用
はたやん
 はたやん
(@はたやん)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

渋木宏明(ひどり)さん、dairygoods さん、たみあ さん
レスありがとうございます。

1、単純に60000件追加するサンプルプログラムを作製し、
ResetContentを発行するとメモリが開放された。
2、出力するべきログ、実行状況メッセージは他APP(自前)にて
発行しているので不正コードは無いモノと思われる。
3、現在の作りから大幅な変更は手がかかるのでリストコントロール
にて作製する。(空きができましたらぜひリストビューコントロール
にて作製してみます。)

以上より、取りあえず「メモリの開放漏れ」から疑ってみます。


返信引用
はたやん
 はたやん
(@はたやん)
ゲスト
結合: 22年前
投稿: 4
Topic starter  

解決しましたーーーーー(^○^)

原因はリストボックスの水平スクロールの対応のため以下ソースを
リストボックスに値を追加毎に処理していました。
開放漏れと言うよりは…なんでしょう…
~略~
/**************************************/
/* 水平スクロール対応 */
/**************************************/
pDc = pVShowList->GetDC(); /* リストボックスのデバイスコンテキストを取得 */

pOldFont = pDc->SelectObject(pVShowList->GetFont());
/* デバイスコンテキストにリストボックスのフォントを指定 */
nSize = pDc->GetTextExtent(出力されるメッセージ).cx;
/* 格納データ雛形の文字列幅取得 */
/* 文字幅最大超判別 */
if(lngVListBoxMaxLine < nSize){ /* 大きい場合 */
lngVListBoxMaxLine = nSize; /* 外部変数に設定 */
pVShowList->SetHorizontalExtent(lngVListBoxMaxLine + 5);
/* 水平スクロール振幅を設定 */
}
~略~

この処理を想定される最大メッセージ長で設定するように変更しOnInintDailogに移動し
追加毎からコメントアウトしました。
直接の原因がGetDC、SelectObject、SetHorizontalExtentのどれなのかは
これから解析します。
取り急ぎ解決報告です。

皆さんありがとうございました。


返信引用
渋木宏明(ひどり)
 渋木宏明(ひどり)
(@渋木宏明(ひどり))
ゲスト
結合: 22年前
投稿: 196
 

解析てか、それしかコードが書いてないなら、ものの見事にリソースリークしてます
よ。

pDc = pVShowList->GetDC();

したら

pVShowList->ReleaseDC(pDC);

で後始末しなくちゃならないし、その間にある

pOldFont = pDc->SelectObject(pVShowList->GetFont());

だって、

pDC->SelectObject (pOldFont);

しなくちゃ駄目です。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました