CStringオブジェクトが作成されるメモリ領域について

[戻る]
ミミ 2006/01/27(金) 14:46:21
いつもお世話になります。ミミです。
環境は、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はアドレスしか持っておらず、「そのもの」がフレームと呼ばれる
# メモリ領域に存在していると考えています。

以上よろしくお願いいたします。

Blue 2006/01/27(金) 14:55:31
> 上記の sMsg を sizeof で計っても4バイトと返って来ます。
これは、sizeof(CString)です。

文字の長さは CString::GetLength で取ってください。
それとも、実際使っているメモリを知りたいのでしょうか?
(CStringはなんか複雑だったような。。。)

επιστημη 2006/01/27(金) 14:57:16
MFCのソースコードを追っかければわかるんだけど、
CStringに関してはライブラリ内部で独自のメモリ管理をやってるみたい。
文字列を真面目にallocateすると小さく刻まれがちだから、
独自のメモリ・プールを用意して、そこから切り出して使ってますね。
それを"フレーム"と称しているんじゃないかしら。

dairygoods 2006/01/27(金) 15:04:07
原文だと、

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 固有の特徴があるようには思えませんけど、
なんで、こんなことに言及してるんでしょうか。

ミミ 2006/01/27(金) 15:33:27
ミミです。

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様の提示してくれた上記と合わせて考えると、このフレーム領域はスタック領域に
配置されると解釈できます。

ミミ 2006/01/27(金) 15:36:52
改行位置が悪く読みにくくなってしまったこと、お許しください。

また、dairygoods様の提示していただいたURLをたどって、
下記URLを参考にさせていただきました。

http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/wcemfc/htm/cstring.asp

tetrapod 2006/01/27(金) 16:00:48
>>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

ITO 2006/01/27(金) 19:28:07
CStringT型ですが、

ttp://www.microsoft.com/japan/msdn/library/default.asp?
url=/japan/msdn/library/ja/vccore/html/vcconMemoryManagementCStringT.asp

Kerry 2006/01/30(月) 13:49:24
つまりこういうことでしょう。

CStringクラスのインスタンス自身はポインタ変数1個だけで、
文字列本体は別途ヒープ上に作成されます。
文字列は参照カウントを使って管理されるので、同一文字列を
指すCStringクラスのインスタンス間で共有されます。

以下のようにCStringクラスのインスタンスを引数として取る
場合は、引数の受け渡しはスタック上でのポインタの受け渡し
で済み、文字列本体をコピーしないので効率的です。

void Foo()
{
    CString a = "あいうえお";
    Bar(a);
}

void Bar(CString b)  // <-- a と同じ文字列実体を参照する
{
    AfxMessageBox(b);
}

ミミ 2006/01/30(月) 23:22:05
[[解決]]
ミミです。

tetrapod 様、ITO 様、Kerry 様、
ご返信ありがとうございます。

>tetrapod 様
自分の英文の誤解釈に対するご指摘、ありがとうございました。

ITO 様が提示してくれましたリンク先に
>一般的なアプリケーションでは、このメモリ割り当て方法で十分です。
と記載されていました。
CString を 普通に使う分には、(今までもそうでしたが…)特にメモリについて考える必要は
ないという事がわかりました。

Kerry 様のご意見にもあるとおり、
やはり CString インスタンスはアドレスしか持たず、
(επιστημη 様もご指摘してくれましたが)実際のメモリ管理等は、
CString クラスの中で処理していると割り切って考えることにします。

# そもそも MFC というのが、ブラックボックス的な要素ですし・・。


>【ミミ 2006/01/27(金) 15:33:27】
>このフレーム領域はスタック領域に配置されると解釈できます。
            ↓
「このフレーム領域(文字列そのもの)はヒープ領域に配置されると解釈できます。」
と言うことで、本件はこれで解決とさせていただきます。

皆様、ありがとうございました。

古いスレッドには追加発言できません。