いつもお世話になります。ミミです。
環境は、Win2000、eMbedded Visual C++4.0、MFC使用です。
前回の私のスレッド「スタック領域について」からの派生質問です。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200601/06010008.txt
OnHoge()::OnButton1(){
CString sMsg;
sMsg = あいうえお;
}
と記述した時、
【MSDNより引用】----
ヒント CString オブジェクトはできる限りヒープ領域ではなく、フレーム上に確保します。
これは、メモリの消費を抑え、引数の渡し方を単純化します。
-------------------
とありますが、ここでいう「フレーム上」というのはどこの空間の事を言うのでしょうか?
スタックの事を言っているのでしょうか?
# 上記の sMsg を sizeof で計っても4バイトと返って来ます。
# どんな文字列を代入しても、結果は4バイトです。
# 個人的には、sMsgはアドレスしか持っておらず、「そのもの」がフレームと呼ばれる
# メモリ領域に存在していると考えています。
以上よろしくお願いいたします。
> 上記の sMsg を sizeof で計っても4バイトと返って来ます。
これは、sizeof(CString)です。
文字の長さは CString::GetLength で取ってください。
それとも、実際使っているメモリを知りたいのでしょうか?
(CStringはなんか複雑だったような。。。)
MFCのソースコードを追っかければわかるんだけど、
CStringに関してはライブラリ内部で独自のメモリ管理をやってるみたい。
文字列を真面目にallocateすると小さく刻まれがちだから、
独自のメモリ・プールを用意して、そこから切り出して使ってますね。
それをフレームと称しているんじゃないかしら。
原文だと、
http://msdn.microsoft.com/library/en-us/wcemfc/htm/cstring_8.asp
| Tip Where possible, allocate CString objects on the stack rather
| than on the heap. This saves memory and simplifies parameter passing.
ですね。
オブジェクトそのものの確保場所については、
特に CString 固有の特徴があるようには思えませんけど、
なんで、こんなことに言及してるんでしょうか。
ミミです。
Blue様、επιστημη様、dairygoods様、早速のお返事ありがとうございます。
あるゴミプログラムを作っていた際、本来であればヒープ上に領域を作成して文字列を代入する
所を
(ゴミプロという事で)少々横着し、OnButton1()の中にローカル変数としてCStringオブジェク
トを作り、
そこに代入していました。
# もちろん、正規に開発しているプログラムでは、予めヒープ上に領域を作成し、そこへ文字列
代入等を
# 行っています。
ここで、前回のスレッドにもありますとおり、スタックサイズは CE では 58KB という事を思
い出し、
CString型のオブジェクトに例えばたくさんの文字列を代入した場合、それはスタックサイズを
圧迫するのでは
ないかと思って調査したところ、sizeofでも4としか返って来なかった・・・という経過で
す。
その上で、
>Blue様
>実際使っているメモリを知りたいのでしょうか?
はい、メモリの使用量を知りたかった為です。文字列長ではありません。ご指摘ありがとうござ
いました。
>dairygoods様
>なんで、こんなことに言及してるんでしょうか。
普通なら考えもしない事なのかも知れませんが、スタック圧迫によるスタックオーバーフローの
問題に
遭遇した為、ちょっとの事でもつい過敏になって考えてしまった為です。
CStringは簡単に使えて便利なクラスではありますが、使いすぎてたくさんの文字列を代入する
と、
結局はスタックを消費してしまうのかと思った為です。
>allocate CString objects on the stack rather than on the heap.
ヒープよりもスタックに確保されるような事が書かれていますね。
という事は、やはりCStringも使いすぎには注意しないといけないという事ですね。
>επιστημη様
ソースコードを追っていただき、ありがとうございます。
なるほど…、独自に別処理しているとするなら、私が定義したsMsgにはやはりアドレスしか持
たないと
納得できます。
dairygoods様の提示してくれた上記と合わせて考えると、このフレーム領域はスタック領域に
配置されると解釈できます。
改行位置が悪く読みにくくなってしまったこと、お許しください。
また、dairygoods様の提示していただいたURLをたどって、
下記URLを参考にさせていただきました。
http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/wcemfc/htm/cstring.asp
>>allocate CString objects on the stack rather than on the heap.
>ヒープよりもスタックに確保されるような事が書かれていますね。
いや翻訳が違う。
ここは命令形なので「ヒープではなくスタックに取れ」という意味。
最初の邦訳が「フレーム」と呼んでいる領域はスタックのことでしょう。
# new せず auto で作れ、ということだろう。あたりまえ。わざわざ言及する内容とも思えな
い。
sizeof CString が 4 なのはそういう実装にしてあるから。
メンバ変数がポインタ1個だけ、という実装に故意にしてあるため。
既にコメントがあるように CString 1個をスタックに取ると、消費スタック量は4
実際の文字列本体は独自に取ったヒープに入ります。
ああ、だから auto で取った CString でも文字列本体はヒープに行くから、
「ヒープに文字列を取りたいからという理由で CString 自体を new する必要は無い」
ということを主張したいのかも >> MS
CStringT型ですが、
ttp://www.microsoft.com/japan/msdn/library/default.asp?
url=/japan/msdn/library/ja/vccore/html/vcconMemoryManagementCStringT.asp
つまりこういうことでしょう。
CStringクラスのインスタンス自身はポインタ変数1個だけで、
文字列本体は別途ヒープ上に作成されます。
文字列は参照カウントを使って管理されるので、同一文字列を
指すCStringクラスのインスタンス間で共有されます。
以下のようにCStringクラスのインスタンスを引数として取る
場合は、引数の受け渡しはスタック上でのポインタの受け渡し
で済み、文字列本体をコピーしないので効率的です。
void Foo()
{
CString a = あいうえお;
Bar(a);
}
void Bar(CString b) // <-- a と同じ文字列実体を参照する
{
AfxMessageBox(b);
}
ミミです。
tetrapod 様、ITO 様、Kerry 様、
ご返信ありがとうございます。
>tetrapod 様
自分の英文の誤解釈に対するご指摘、ありがとうございました。
ITO 様が提示してくれましたリンク先に
>一般的なアプリケーションでは、このメモリ割り当て方法で十分です。
と記載されていました。
CString を 普通に使う分には、(今までもそうでしたが…)特にメモリについて考える必要は
ないという事がわかりました。
Kerry 様のご意見にもあるとおり、
やはり CString インスタンスはアドレスしか持たず、
(επιστημη 様もご指摘してくれましたが)実際のメモリ管理等は、
CString クラスの中で処理していると割り切って考えることにします。
# そもそも MFC というのが、ブラックボックス的な要素ですし・・。
>【ミミ 2006/01/27(金) 15:33:27】
>このフレーム領域はスタック領域に配置されると解釈できます。
↓
「このフレーム領域(文字列そのもの)はヒープ領域に配置されると解釈できます。」
と言うことで、本件はこれで解決とさせていただきます。
皆様、ありがとうございました。