ページ 11

メモリの割り当てについて

Posted: 2010年7月27日(火) 11:35
by シエル
いつもお世話になっております。シエルです。

メモリの割り当てについて質問があります。

【質問1】
下記三つのものに割り当てられるメモリの領域は下記領域で正しいでしょうか?

①グローバル変数、staticを付けた変数
→静的領域

②自動変数
→スタック領域

③newやmallocなどを使って確保した領域
→ヒープ領域

【質問2】
下記三つのものが割り当てられるタイミングは下記のとおりで正しいでしょうか?

①グローバル変数、staticを付けた変数
→プログラム起動時

②自動変数
→その変数がある関数が呼ばれたタイミング

③newやmallocなどを使って確保した領域
→newやmallocなどで動的確保したタイミング

【質問3】
下記三つのものが確保できる上限サイズについて教えてください

①グローバル変数、staticを付けた変数
→わかりません

②自動変数
→わかりません

③newやmallocなどを使って確保した領域
→メモリがある限りいくらでもOK?

基本的な質問で申し訳ございませんが、ご回答よろしくお願い致します。

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 11:54
by たかぎ
newが出てきているのでC++だとは思いますが、詳しい処理系不明ですので正確なことはいえないのですが...

>【質問1】
> 下記三つのものに割り当てられるメモリの領域は下記領域で正しいでしょうか?
>
> ①グローバル変数、staticを付けた変数
> →静的領域

原則としてそうです。

> ②自動変数
> →スタック領域
>
> ③newやmallocなどを使って確保した領域
> →ヒープ領域

そうなる処理系もあります。

> 【質問2】
> 下記三つのものが割り当てられるタイミングは下記のとおりで正しいでしょうか?
>
> ①グローバル変数、staticを付けた変数
> →プログラム起動時

メモリが割り当てられるという意味ではそうです。
初期化のタイミングはまた別ですが...

> ②自動変数
> →その変数がある関数が呼ばれたタイミング

そうなる場合もあります。

> ③newやmallocなどを使って確保した領域
> →newやmallocなどで動的確保したタイミング

おおむねそうですが、newの場合はいろいろなケースがあります。

>【質問3】
> 下記三つのものが確保できる上限サイズについて教えてください
>
> ①グローバル変数、staticを付けた変数
> →わかりません

完全にコンパイラや実行環境に依存します。

> ②自動変数
> →わかりません

完全にコンパイラや実行環境に依存します。

> ③newやmallocなどを使って確保した領域
> →メモリがある限りいくらでもOK?

完全にコンパイラやライブラリの実装、実行環境に依存します。

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 11:59
by シエル
環境書き忘れてました。。。

visual c++ 2008 ExpressEdition
Windows7
メモリ4GB

です。

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 19:03
by シエル
すいません。追加で質問です。
下記のようなクラスを

class A{
int x,y,z;
double o,p,q;
public:
A();
~A();
};

A *a=new A

としてインスタンスを作成した場合、
メンバ変数のメモリは全てヒープ領域に確保されるのでしょうか?

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 22:21
by Poco
VC++ですよね?
ヒープ領域に確保されます。
#operator newとかを上書きしないことが前提ですよね?

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 22:36
by シエル
ぽこさんありがとうございました!

グローバル変数の限界サイズが来たときの対応が分かってよかったです。
クラスで変数を定義して、動的に確保すればメモリがなくなることはなさそうですね。

基本をあまり知らないので、operator newの意味がさっぱり分かりませんでしたが、
さっきググって調べました。
オーバーロードすれば、別で確保しといた領域にオブジェクトを構築できるんですね。
勉強になりました。

たかぎさんもありがとうございました。

これにて解決と致します。

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 23:09
by Poco
> グローバル変数の限界サイズが来たときの対応が分かってよかったです。
> クラスで変数を定義して、動的に確保すればメモリがなくなることはなさそうですね。

揚げ足を取る様で申し訳ないのですが、
グローバル変数を限界サイズまで取ったときは、
ヒープも使えない状況に追い込まれると思いますよ。

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 23:17
by シエル
静的領域とヒープ領域の限界サイズは同じってことでしょうか?

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 23:22
by Poco
1つのプロセスに割り当てられるメモリサイズに上限があるからです。
32ビットOSだと高々4GB、64ビットOSだともっとたくさんです。
この辺はOS(やその設定)ごとに異なるので、具体的な数値は出せません。
いずれにしろ、コード領域、データ領域、ヒープ領域、スタック領域もろもろ合わせて上限があります。

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 23:28
by シエル
なるほど。
私が質問する前までは静的領域はそんなに確保できないのかな~と思ってました。
だからいつか限界が来たらどうしようと思っていたのですが、数十MBで無くなるほど
少ないわけではなさそうですね。

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

Re:メモリの割り当てについて

Posted: 2010年7月27日(火) 23:40
by ISLe
Visual C++ 2008 Express Editionで、ヒープサイズは既定で1MB、スタックサイズも既定で1MBだそうです。

プロジェクトのプロパティ→構成プロパティ→リンカ→システム

Re:メモリの割り当てについて

Posted: 2010年7月28日(水) 01:00
by 組木紙織
>1つのプロセスに割り当てられるメモリサイズに上限があるからです。
>32ビットOSだと高々4GB、64ビットOSだともっとたくさんです。
>この辺はOS(やその設定)ごとに異なるので、具体的な数値は出せません。
>いずれにしろ、コード領域、データ領域、ヒープ領域、スタック領域もろもろ合わせて上限があります。


ヒープ領域も4GBの中にふくまれるのでしょうか?
私は、コード領域+データ領域+スタック領域もろもろ合わせて4GBという認識です。

#32bitCPUでメモリモデルはflatを想定しています。

Re:メモリの割り当てについて

Posted: 2010年7月28日(水) 01:26
by Poco
> ヒープ領域も4GBの中にふくまれるのでしょうか?
> 私は、コード領域+データ領域+スタック領域もろもろ合わせて4GBという認識です。
>
> #32bitCPUでメモリモデルはflatを想定しています。

含まれます。
組木紙織さんの認識ですと、一つのプロセスに割り当て可能な仮想メモリとは別腹で、
ヒープ領域がプロセスに割り当てられることになりませんか?

OSがプログラム(実行可能ファイル)を実行する際には、プロセスという管理実体を作成し、
プログラム内に記録されている、各領域(コード領域、データ領域、スタック領域、BSS領域
(上記ヒープ領域と言っていたものを言い直しました))のサイズを読み取り、それに合わせて、
プロセスに(仮想)メモリを割り当てます。

そのメモリに対して、プログラムローダがコード領域、データ領域を展開します。
スタック領域や、BSS領域の初期化等は誰がやるか知りません(OSかもしれないし、
ランタイムライブラリかもしれない)><b。
しかし、OSで言うところのBSS領域(ランタイムライブラリで言うところのヒープ)が足りなくなると、ランタイムライブラリはOSにメモリを要求します。
この際に、求めるメモリがBSS領域のものだからと言って、OSが仮想メモリとは違うメモリを渡すことはないと思います。

----追記
長々と訳の分からないこと書いちゃった気がしますが、一言でいうと、
「ヒープ領域もOSが提供する仮想メモリ上にあるのだから、含まれます。」
ですね。
画像

Re:メモリの割り当てについて

Posted: 2010年7月28日(水) 07:29
by シエル
すいません。変なこと聞きます。


>長々と訳の分からないこと書いちゃった気がしますが、一言でいうと、
>「ヒープ領域もOSが提供する仮想メモリ上にあるのだから、含まれます。」
>ですね。

ヒープ領域は「仮想」メモリ上に確保されるのですか?
物理メモリは使用されないのでしょうか?

Re:メモリの割り当てについて

Posted: 2010年7月28日(水) 08:38
by 組木紙織
>ヒープ領域は「仮想」メモリ上に確保されるのですか?
>物理メモリは使用されないのでしょうか?

この場合の"仮想メモリ"はOSが提供する論理的な意味でのメモリという意味で、実際に確保される場所は
考えていません。

>ぽこさん

なんとなく話してる意味は分かりますが、細かい部分が全然です。(BSS領域って何?とか、)

私の認識だと、プログラム起動後すぐに、セグメントレジスタにそれぞれのアドレス(コード、データ、スタック)を入れて管理し、セグメントが最大4Gです。
BSS領域なんて出てこないです。

#多分対象としている領域が違う感じがしてます。
#私はアセンブラでコーディング時のレベルで話してます。

Re:メモリの割り当てについて

Posted: 2010年7月28日(水) 11:47
by ちょっと通りますよ
>ヒープ領域は「仮想」メモリ上に確保されるのですか?
>物理メモリは使用されないのでしょうか?
仮想のイメージが違うかな? 必ず対応する物理領域があります
プログラム(プロセス)からは、仮想アドレスしか認識できないので
イメージ(仮想記憶の概念図)ttp://ja.wikipedia.org/wiki/%E4%BB%AE%E6%83%B3%E8%A8%98%E6%86%B6

ウィンドウズの場合だと、ヒープマネージャーが管理している領域がヒープ領域に当たります
プロセスが起動するときに、例えばデフォルトで1Mの領域をヒープマネージャに対して予約し、
デフォルトで8kをコミット(確定)します
物理メモリ(仮想メモリ)として使われるのはコミットされた場所だけです
実使用上コミットした8kを超える場合は、予約領域1Mまで自動拡張され使用できます

ちなみに、OSについてるヒープマネージャーとの交渉は、HeapAllocだったかな(Win32API)で
mallocの中でHeapAllocを呼び出しています
ページ(デフォは4k)単位でしか領域を確保できない為、mallocはひとまず4kとか8kとかの領域を確保し、
プロセス(ユーザ)から要求があるごとに、その領域を切り崩しながらヒープとして割り当てます

※コミットのイメージとしては、仮想アドレス空間と物理アドレス空間を対応付ける作業

>組木紙織さん
↑のURLの項目「仮想アドレス空間管理」にも、BSSについて触れていますよ

Re:メモリの割り当てについて

Posted: 2010年7月28日(水) 12:08
by シエル
>>組木紙織さん、ちょっと通りますよさん

ありがとうございます。イメージがつかめました。

Re:メモリの割り当てについて

Posted: 2010年7月29日(木) 01:18
by Poco
> >ぽこさん
>
> なんとなく話してる意味は分かりますが、細かい部分が全然です。(BSS領域って何?とか、)

え~と、全然何でしょうか?(意味不明ですか?、納得がいかないですか?)

> 私の認識だと、プログラム起動後すぐに、セグメントレジスタにそれぞれのアドレス(コード、データ、スタック)を入れて管理し、セグメントが最大4Gです。
> BSS領域なんて出てこないです。

アセンブリ言語と実行イメージでのメモリ空間の分類(概念)が違うから、
出てこなくて当然です。