- PR -

MFC CString の大量連結

投稿者投稿内容
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-02-27 12:30
ほむらです。
WindowsAPIの場合、フラグメンテーションを極力起こさない方法もあります。

CreateHeap(?)を使用することです。
同じサイズのメモリ確保ならばフラグメンテーションは起こりにくくなりますから。
またエディットコントロールは64kという制限もあるので1ページ確保するだけでも
十分かな?
メモリリークを発生させないためにもCreateHeap()系は使ったほうがいいですね。
基本的な使い方としては手抜き用途が多いですけど同じサイズを大きく確保するという面で
フラグメンテーションを抑える効果もあります

#DDEはあまり関係なかったですね。
#検索するのならEM_ 挿入 エディットかな?
#どちらにしても、追加するデータにもよるので一概に別の方法があるとはいえません。
弟子
会議室デビュー日: 2004/02/03
投稿数: 11
投稿日時: 2004-02-27 13:00
MSのCStringの説明より
http://www.microsoft.com/JAPAN/developer/library/vcmfc/_mfc_cstring.htm
>CString オブジェクトはできる限りヒープ領域ではなく、フレーム上に確保します。これは、メモリの消費を抑え、引数の渡し方を単純化します。

ヒープに確保することで、この利点が失われてしまうかも?実際に調べてない+完全な理解がない のでなんとも言えないですけど(^^;)
ケースバイケースという事なのでしょうか。

MFC + CStringを使う前提で、文字列操作でメモリフラグメンテーションを考えたことが
無かった為、非常に気になります。
私がそういう条件での実装を求められたら、まずCStringは使いませんけど。
takashi
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 79
お住まい・勤務地: 東京
投稿日時: 2004-02-27 13:37
>もし、先行してメモリを確保する必要があるなら・・・CStringArrayというものがあります。
う〜ん、でも結局表示する前に全て連結する必要があるような・・><

>人のいうことを鵜呑みにしてはいけません。
おっしゃる通りです;; 詳しい説明ありがとうございます^^

>メモリリークを発生させないためにもCreateHeap()系は使ったほうがいいですね。
なるほど、初めて聞きました。調べてみますね^^

>ヒープに確保することで、この利点が失われてしまうかも?
その辺、大量連結の時はまた変わってくるかもしれないですね。調べてみます^^

>私がそういう条件での実装を求められたら、まずCStringは使いませんけど。
T-T
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-02-27 13:47
ども、ほむらです。
適当なので間違えていたら突っ込みお願いします。
-----
>CString オブジェクトはできる限りヒープ領域ではなく、
>フレーム上に確保します。これは、メモリの消費を抑え、引数の渡し方を単純化します。
ここでいう、フレームとはスタックではないかなと。。。
つまり。
CString *pstrText = new CString; *pstrText = _T("");
とするのではなくて
CString strText = _T("");
とすべきといっているのではないかと思います。

スタック上に作成すればデータセグメントとは別ですから
メモリ消費を抑えることもできるでしょうし、
ベースアドレスから位置を特定できるから引数指定の単純化できる
とか言っているのではないかなと。(引数についてはこじつけまがいですが^^;;;)

>MFC + CStringを使う前提で、文字列操作でメモリフラグメンテーションを考えたことが
>無かった為、非常に気になります。
おなじく、WINAPIでメモリの使用量についてはあまり考えたことがないです。
ただ、フラグメンテーションの関係があるので
極力同じサイズでの開放と確保には注意しましたが。。。

>私がそういう条件での実装を求められたら、まずCStringは使いませんけど。
低級なことするのが一番使用の効率はいいですけどね^^;;;;

---
Jitta氏へ
メモリをデフラグしてくれるというのはBASICとかGCですよね。
CだとSTLみたいなものでGCもどきがあったような。。。。(smart_ptrではないですよ)

ちなみに、WindowsでもSunOSと似たようなことにはなりますね
連続するアドレスで確保できないとOUT_OF_MEMORY(?)の例外が発生する
(普段はcatchせずNULLとかINVALID_HANDLEで調べてしまっていますけど(笑)

6はページファイルかな?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-27 13:52
引用:

弟子さんの書き込み (2004-02-27 12:13) より:

私は「メモリ効率の悪さ」を「オブジェクトのインスタンス生成時のオーバーヘッド」と
解釈して返答をしました。
その他メモリフラグメンテーション等は考慮していません。


 す、すみません!! takashiさんに「この書き方じゃいろんな意味に取れるよ」というつもりで書いたもので、弟子さんがどうこうというつもりではありません。。。


> CStringArray
 名前からして、「文字列の配列」・・・char strArray[][]のような?
"aaa"
"bbb"
"ccc" って感じのヤツです。


>>>takashiさん
で、結局「どういう場面で」「どのように使う」のでしょう?

 例えば、どんなにフラグメンテーションをおこすような作りにしても、短時間(ユーザが見ている間)で実行が終了するなら、全く気にしなくてもかまいません。OSが、そのアプリケーションのために割り当てるメモリ内だけで済む話ですから(ヒープ使うとOSのグローバルに取られますから、注意)。
 しかし何らかのサーバで、長時間無休で動き続けるなら、やはり気にしなければなりません。その場合、CStringTクラスから派生して自作します。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-27 14:01
引用:

ほむらさんの書き込み (2004-02-27 13:47) より:

メモリをデフラグしてくれるというのはBASICとかGCですよね。
CだとSTLみたいなものでGCもどきがあったような。。。。(smart_ptrではないですよ)

ちなみに、WindowsでもSunOSと似たようなことにはなりますね
連続するアドレスで確保できないとOUT_OF_MEMORY(?)の例外が発生する
(普段はcatchせずNULLとかINVALID_HANDLEで調べてしまっていますけど(笑)


 ええ!!BASICって、デフラグしてくれるんですか?!って、VBのことじゃないですね

 Javaは、ガベージコレクトの時にデフラグもしてくれるんですよねぇ?.NETも、そうだったような?ただ、aspnet_wpは、再起動することで最適化しやがることがあるらしい。。。(たまにつながっているはずのセッションが切れる)

 ページファイルやWindowsのメインメモリは、2番目のフラグメントをして割当をするみたいですね。メモリの方は、ページアウトすることで一旦解放し、ページインするときには(連続した空きがあれば)フラグメントが解消する、と。


 そういえば、某携帯会社の「キャリア間メールシステム」に携わりましたが、その時には気にしなかったなぁ。まぁ、確保の逆順に解放すれば、フラグメンテーションは発生しませんし。。。処理系に因るけど。
takashi
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 79
お住まい・勤務地: 東京
投稿日時: 2004-02-27 14:10
引用:

Jittaさんの書き込み (2004-02-27 13:52) より:
>>>takashiさん
で、結局「どういう場面で」「どのように使う」のでしょう?



ローカルで単体で動作するアプリケーションです。処理としては構造体の配列(要素数約1,000〜10,000)の各要素のメンバをCString のFormatメソッド(sprintfみたいなもの)で整形してCStringオブジェクトにして、それをFor文でまわして改行とともに連結し(リスト形式にしたいがため)、CEditコントロールにSetWindowTextメソッドでセットし画面に表示するというものです。

引用:

例えば、どんなにフラグメンテーションをおこすような作りにしても、短時間(ユーザが見ている間)で実行が終了するなら、全く気にしなくてもかまいません。OSが、そのアプリケーションのために割り当てるメモリ内だけで済む話ですから(ヒープ使うとOSのグローバルに取られますから、注意)。



なるほど、確かにそうかもしれませんね。ただ、扱うデータが非常に多いプログラムなので各処理で無駄がないようにしようと思い、もっといい方法があるかもしれないという考えで投稿した次第です。
なかなか僕の知らない有意義な話がいろいろ聞けてよかったと思っています^^
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-02-27 14:12
ほむらです。
ちょっとだけスレッドの話に戻って。。

>>もし、先行してメモリを確保する必要があるなら・・・CStringArrayというものがあります。
>う〜ん、でも結局表示する前に全て連結する必要があるような・・><
僕が一番気になるのは、エディットコントロールへ文字列を表示するために
なぜ、文字列を連結するという操作が入るのかが疑問なのですよね。
CStringを使っているのであればある程度の編集機能を持っているはずなのですけどね。
MFCならばDDEとか使ってコントロールとメンバ変数を直結できますし。。。

ここで公開すべきは
何のために文字列を連結しているのか
なぜ、文字列を行単位で別々に保持する必要があるのか。
結果として何を実現できればいいのか
だと思うのですよね。

どんなに効率的な方法であっても仕様にそぐわなければ
ボツなのですし。
---
Jitta氏とかぶったので以下追記^^;;;;
[quote]
ローカルで単体で動作するアプリケーションです。処理としては構造体の配列(要素数約1,000〜10,000)の各要素のメンバをCString のFormatメソッド(sprintfみたいなもの)で整形してCStringオブジェクトにして、それをFor文でまわして改行とともに連結し(リスト形式にしたいがため)、CEditコントロールにSetWindowTextメソッドでセットし画面に表示するというものです。
[/quote]
このやり方ならば整形の時点で全体の文字数がわかるので
あらかじめメモリを確保しておいてCopyMemory(?)とかで内容をコピーしたほうが
いいのではなんて思ってみたり。


[ メッセージ編集済み 編集者: ほむら 編集日時 2004-02-27 14:23 ]

スキルアップ/キャリアアップ(JOB@IT)