メモリの格納領域について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Fimbul
記事: 100
登録日時: 8年前

メモリの格納領域について

#1

投稿記事 by Fimbul » 7年前

コード領域 全関数の格納領域
データ領域 グローバル変数・インスタンス、静的変数・インスタンスの格納領域
スタック領域 仮引数、戻り値?、ローカル変数・インスタンスの格納領域
ヒープ領域 動的変数・インスタンスの格納領域


メモリの格納領域は上記の様な感じだと思うのですが、インスタンスの格納とはメンバ変数の格納と言う事でしょうか。
そう仮定して書きますが、

・ローカルインスタンスのメンバ変数はスタック領域に格納される。
・静的インスタンスのメンバ変数はデータ領域に格納される。

と言う事で良いのでしょうか。


また、画像等をロードすると関数がハンドルやアドレスを返すので、それを介して処理をすると思いますが、読み込まれた画像等の実体はどこに格納されるのでしょうか。
関数内部で動的にメモリを確保しているのでしょうか。

アバター
SUE
記事: 41
登録日時: 7年前

Re: メモリの格納領域について

#2

投稿記事 by SUE » 7年前

すみません、後半しか答えられませんが・・・
Fimbul さんが書きました: また、画像等をロードすると関数がハンドルやアドレスを返すので、それを介して処理をすると思いますが、読み込まれた画像等の実体はどこに格納されるのでしょうか。
関数内部で動的にメモリを確保しているのでしょうか。
はい。画像のメモリ確保は動的に行われます。そうでなければコード上(あるいはスタティックリンクライブラリ)に画像データが含まれていることになってしまいますから。

で、問題はそれがどこに確保されるのかということです。

PCに専用のグラフィックボードが搭載されているとき、画像など描画関係のデータはほとんど、グラフィックボード上のメモリに読み込まれます。
(但しそれが足りないときや、あらかじめ使わないよう指定したとき、あるいはそもそもボードが無いときはメインメモリが使われます。)
こういうメモリには普通アクセスすることが出来ないので、DirectXなどのAPIというプラックボックスを介してデータを操作します。

DirectXの場合(あるいは、それを利用しているDXライブラリ)しか知らないのですが、大抵はこんな感じです。
pop'n music 20 fantasia ポップンクエストPhase MAX Ⅱ ムラクモ/少年は空を辿る【Power Of Nature】

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: メモリの格納領域について

#3

投稿記事 by softya(ソフト屋) » 7年前

Fimbul さんが書きました:・ローカルインスタンスのメンバ変数はスタック領域に格納される。
・静的インスタンスのメンバ変数はデータ領域に格納される。
Windows等に環境を限定すれば、そういう認識で合っていると思います。
Fimbul さんが書きました:また、画像等をロードすると関数がハンドルやアドレスを返すので、それを介して処理をすると思いますが、読み込まれた画像等の実体はどこに格納されるのでしょうか。
関数内部で動的にメモリを確保しているのでしょうか。
使うライブラリにもよりますがOSがメモリを動的確保してハンドルを返す場合もあります。GPU内のメモリ領域に読み込む場合もあります。
あるいは自分で用意した動的確保メモリに画像を格納しているものもあります。

ハンドルも内部テーブルの番号だったり、動的リストの構造体アドレスだったり色々考えられます。
ゲーム機となるとさらにメモリが足らないとかOS自体も無いこともあるので各ソフトは工夫してメモリ管理しています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: メモリの格納領域について

#4

投稿記事 by ISLe » 7年前

インスタンスには仮想関数テーブルが含まれる場合もあるのでメンバ変数だけとは限らないです。

グローバル/ローカルというのはスコープに対して意味を持つ言葉なので、ここでは、静的記憶域期間を持つ~(静的~)、とか、自動記憶域期間を持つ~(自動~)、というほうがふさわしいと思います。

Fimbul
記事: 100
登録日時: 8年前

Re: メモリの格納領域について

#5

投稿記事 by Fimbul » 7年前

SUE さんが書きました: PCに専用のグラフィックボードが搭載されているとき、画像など描画関係のデータはほとんど、グラフィックボード上のメモリに読み込まれます。
(但しそれが足りないときや、あらかじめ使わないよう指定したとき、あるいはそもそもボードが無いときはメインメモリが使われます。)
こういうメモリには普通アクセスすることが出来ないので、DirectXなどのAPIというプラックボックスを介してデータを操作します。
softya(ソフト屋) さんが書きました: 使うライブラリにもよりますがOSがメモリを動的確保してハンドルを返す場合もあります。GPU内のメモリ領域に読み込む場合もあります。
あるいは自分で用意した動的確保メモリに画像を格納しているものもあります。

ハンドルも内部テーブルの番号だったり、動的リストの構造体アドレスだったり色々考えられます。
ゲーム機となるとさらにメモリが足らないとかOS自体も無いこともあるので各ソフトは工夫してメモリ管理しています。
適宜都合が良い所に格納されるのですね。
softya(ソフト屋) さんが書きました: Windows等に環境を限定すれば、そういう認識で合っていると思います。
そうじゃない環境があるとは。
ISLe さんが書きました: インスタンスには仮想関数テーブルが含まれる場合もあるのでメンバ変数だけとは限らないです。
仮想関数テーブルを知らなかったので調べました。
仮想関数を持つとサイズが大きくなるんですね。
C++編(言語解説) 第9章 オーバーライド
http://www.geocities.jp/ky_webid/cpp/language/009.html
ISLe さんが書きました: グローバル/ローカルというのはスコープに対して意味を持つ言葉なので、ここでは、静的記憶域期間を持つ~(静的~)、とか、自動記憶域期間を持つ~(自動~)、というほうがふさわしいと思います。
確かにそうですね。
自動~を全く忘れていました。



追加の質問をさせてください。
「C++の場合、配列を使うならvectorを使え」等と聞きました。

例えば、静的な配列を確保しておき、それにリソースのハンドルやアドレスを格納するとします。
そして、そのリソースが必要無くなれば解放して無駄なメモリの消費を無くせます。
しかし、リソースのハンドルやアドレスを格納していた配列自体は静的変数なのでプロセス中残り続けます。

一方、静的なvectorインスタンスを生成すれば、上記と同じ事をしてもリソースのハンドルやアドレスを格納している配列は動的なのでプロセス中に解放できます。
ですが、今度はvectorインスタンスが静的なのでプロセス中残り続けます。

ならば、vectorインスタンスを動的に生成して、そのアドレスを保持するポインタを静的にすれば、リソースが不要になりメモリを解放した後に残る物は、vectorクラス型へのポインタだけになります。

何が言いたいのかと言いますと、「C++の場合、配列を使うならvectorを使え」の意味は、動的配列の管理が楽であり、無駄なメモリ消費をなくせるからなのでしょうか。
そうだとすると最後のvectorインスタンスを動的に生成する方法が一番良いと思うのですが、何かやり過ぎな感じもします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: メモリの格納領域について

#6

投稿記事 by softya(ソフト屋) » 7年前

Fimbul さんが書きました: 追加の質問をさせてください。
「C++の場合、配列を使うならvectorを使え」等と聞きました。

例えば、静的な配列を確保しておき、それにリソースのハンドルやアドレスを格納するとします。
そして、そのリソースが必要無くなれば解放して無駄なメモリの消費を無くせます。
しかし、リソースのハンドルやアドレスを格納していた配列自体は静的変数なのでプロセス中残り続けます。

一方、静的なvectorインスタンスを生成すれば、上記と同じ事をしてもリソースのハンドルやアドレスを格納している配列は動的なのでプロセス中に解放できます。
ですが、今度はvectorインスタンスが静的なのでプロセス中残り続けます。

ならば、vectorインスタンスを動的に生成して、そのアドレスを保持するポインタを静的にすれば、リソースが不要になりメモリを解放した後に残る物は、vectorクラス型へのポインタだけになります。

何が言いたいのかと言いますと、「C++の場合、配列を使うならvectorを使え」の意味は、動的配列の管理が楽であり、無駄なメモリ消費をなくせるからなのでしょうか。
そうだとすると最後のvectorインスタンスを動的に生成する方法が一番良いと思うのですが、何かやり過ぎな感じもします。
vectorを使うメリットは動的にサイズを拡張してくれることもメリットながら、添字範囲外のガードがされている事などが大きなポイントだと思います。
つまりポインタ問題や添字問題をガード・隠蔽できる安全な使い方と言えるでしょう。
それに対して、vectorインスタンスを動的に生成することで十分なメリットがあるほどメモリ節約になるのでしょうか?安全性を犠牲にするほどのメリットがあるのか?それが問題ですね。

一般にvectorを選ぶのか、配列をnewで確保するのか、あるはリスト構造なのかケースバイケースです。
メリット(速度・メント性・安定性)とデメリット(メモリ増加・低速化・不安定性)などを測りにかけて適材適所で選択します。
全部vectorで良いなんて物はありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Fimbul
記事: 100
登録日時: 8年前

Re: メモリの格納領域について

#7

投稿記事 by Fimbul » 7年前

softya(ソフト屋) さんが書きました: vectorを使うメリットは動的にサイズを拡張してくれることもメリットながら、添字範囲外のガードがされている事などが大きなポイントだと思います。
つまりポインタ問題や添字問題をガード・隠蔽できる安全な使い方と言えるでしょう。
添え字範囲外のガードと言うのはatの事でしょうか。
atは非常に処理に時間がかかると聞いたので[]でアクセスしていました。
softya(ソフト屋) さんが書きました: それに対して、vectorインスタンスを動的に生成することで十分なメリットがあるほどメモリ節約になるのでしょうか?安全性を犠牲にするほどのメリットがあるのか?それが問題ですね。
これがもっとも気になっていた事なのですが、メモリの感覚が乏しく、どの程度からメモリ消費が大きいと言うのか分からないのです・・・。
さすがに中小規模のプログラムで 1 [GB] 使っていれば使い過ぎだと言う事は分かるのですが。
softya(ソフト屋) さんが書きました: 一般にvectorを選ぶのか、配列をnewで確保するのか、あるはリスト構造なのかケースバイケースです。
メリット(速度・メント性・安定性)とデメリット(メモリ増加・低速化・不安定性)などを測りにかけて適材適所で選択します。
全部vectorで良いなんて物はありません。
メント性とはメンテ(メンテナンス)性の事でしょうか。
そうだとして、vector new[] listの場合、メンテ性、安定性、とは具体的にどういう事なのでしょう。
また、速度 : (遅) list vector new[] (速) でよろしいのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: メモリの格納領域について

#8

投稿記事 by softya(ソフト屋) » 7年前

Fimbul さんが書きました:
softya(ソフト屋) さんが書きました: vectorを使うメリットは動的にサイズを拡張してくれることもメリットながら、添字範囲外のガードがされている事などが大きなポイントだと思います。
つまりポインタ問題や添字問題をガード・隠蔽できる安全な使い方と言えるでしょう。
添え字範囲外のガードと言うのはatの事でしょうか。
atは非常に処理に時間がかかると聞いたので[]でアクセスしていました。
そうですねatの事です。聞いた話だけでなく自分でatがどのぐらい遅いか実験してみることも大事ですよ。
Fimbul さんが書きました:
softya(ソフト屋) さんが書きました: それに対して、vectorインスタンスを動的に生成することで十分なメリットがあるほどメモリ節約になるのでしょうか?安全性を犠牲にするほどのメリットがあるのか?それが問題ですね。
これがもっとも気になっていた事なのですが、メモリの感覚が乏しく、どの程度からメモリ消費が大きいと言うのか分からないのです・・・。
さすがに中小規模のプログラムで 1 [GB] 使っていれば使い過ぎだと言う事は分かるのですが。
これも同じですが実験して自分で実感を掴むべきです。
32bit環境ならポインタは確かに4バイトでvectorインスタンスより小さいですが、vectorインスタンスが沢山プログラム中で度々生成と消滅しな限りさほど意味はないと思います。
vectorインスタンスが何バイトか調べて見ましたか?1つで困るほど大きなサイズでしょうか?じゃあ100個だったら?
プログラム内で使う数は予想できますよね。だったら予備計算できるはずです。

で、一般的なアプリやゲームプログラムがメモリをどのぐらい消費しているかはタスクマネージャで見てみましょう。
Fimbul さんが書きました:
softya(ソフト屋) さんが書きました: 一般にvectorを選ぶのか、配列をnewで確保するのか、あるはリスト構造なのかケースバイケースです。
メリット(速度・メント性・安定性)とデメリット(メモリ増加・低速化・不安定性)などを測りにかけて適材適所で選択します。
全部vectorで良いなんて物はありません。
メント性とはメンテ(メンテナンス)性の事でしょうか。
そうだとして、vector new[] listの場合、メンテ性、安定性、とは具体的にどういう事なのでしょう。
また、速度 : (遅) list vector new[] (速) でよろしいのでしょうか。
失礼しました。メンテ性の打ち間違いです。
vectorやlistを使ったほうが安定性やメンテ性で有利ですが速度は犠牲になります。それにサイズ可変の配列でもプログラム起動中に何度もサイズが変わらなくて添字上限下限をガード出来るならnew[]で生成したほうがシンプルでメンテ性が高いかも知れません。
速度に関しては、シーケンシャルアクセスとランダムアクセスでlistとvectorでは速度優位が変わります。なのでケースバイケースです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Fimbul
記事: 100
登録日時: 8年前

Re: メモリの格納領域について

#9

投稿記事 by Fimbul » 7年前

softya(ソフト屋) さんが書きました: vectorやlistを使ったほうが安定性やメンテ性で有利ですが速度は犠牲になります。それにサイズ可変の配列でもプログラム起動中に何度もサイズが変わらなくて添字上限下限をガード出来るならnew[]で生成したほうがシンプルでメンテ性が高いかも知れません。
速度に関しては、シーケンシャルアクセスとランダムアクセスでlistとvectorでは速度優位が変わります。なのでケースバイケースです。
「C++なら配列よりvector」主義の様なものがあるのかと思い、すっきりしました。
やはり、ケースバイケースが大切なんですね。


SUEさん、softyaさん、ISLeさん、返信ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る