質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

Q&A

解決済

3回答

2892閲覧

配列 1億個

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

0グッド

0クリップ

投稿2016/09/26 11:56

編集2016/09/26 12:35

.#define MAXPT 100000000
float t[MAXPT][3];

このように配列を作りました。
本当はmalloc()を使いますけど・・・・
当然ながら、Segmentation faultになりました。

そうなると、float = 32ビット = 4byte

4 * 3 * 100000000 = 1.2Gbの領域が必要になるはずです。
この場合、「OSは1.2Gbすべての配列を一度にメモリ上に展開させる」ということでしょうか??

10億個の配列を使用した場合、12x10^9になるので、メモリは12GB搭載していないと動かない・・・ということでしょうか?

「追記」
OSが ”巨大すぎる実行ファイルの場合、「一度に全てをメモリ上に展開する」のではなく、必要な部分を「小さく分割」して、実行している可能性” はないのかなぁ・・・と思いました。
実際にはどうなんでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

おそらくその配列は、ローカル変数として宣言したものではないかと思います。

ローカル変数として配列を確保した場合、スタックポインタをずらすことで取られますが、スタックは通常数MBもあればいいほうなので、スタックポインタを1.2GB分もずらすと、次に使った時点でスタックエリアを外れてしまいます。ということで、関数内で巨大なローカル配列を確保するのは、基本やるべきでないことです。

関数の外などで静的変数として用意する場合は、プログラム起動時に確保しますので、足りなければスワップが起きるかメモリ不足で起動に失敗するか、だと思います。

投稿2016/09/26 12:37

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2016/09/26 12:41

ローカル内と静的変数とで違うということですね。 ありがとうございます。
strike1217

2016/09/26 12:57 編集

おおおお〜〜 int main()の外に置いたら、Segmentation faultは起きずに、実行されました。 次々にメモリ使用量が増大していきました。 まぁ・・・当然ですね・・・
guest

0

ベストアンサー

strike1217 さんの一連の質問から OS は Linux、CPU アーキテクチャは x86_64 が前提でよいでしょうか。

4 * 3 * 100000000 = 1.2Gbの領域が必要になるはずです。

この場合、「OSは1.2Gbすべての配列を一度にメモリ上に展開させる」ということでしょうか??

「メモリ上に展開する」の意味が微妙ですが、初期値なしのデータセグメント(.bss)ですので、ゼロが連続する擬似ファイルにマッピングされます。これは /dev/zero をマッピングしたのと同義です。つまり、予約はされます(この詳細がまた難しいけど)が、その実体がすぐに用意されるわけではありません。

まずは、メモリマッピングの概念について勉強して頂く必要があります。OSが管理するメモリはページングによって、すべてなんらかのディスク上のデータとマッピングされる(=対応付けられる)と考えてください。それは、スワップかもしれませんし、実行可能ファイルのテキストセグメントかもしれませんし、/dev/zero のようなデバイスかもしれません。
/dev/zero は永遠にゼロが続くデバイスですので、どこを読み出してもゼロの連続しか出てきません。
今、この変数tの先頭アドレスが /dev/zero のオフセット0にマッピングされたとします。配列の100000000個めの要素にアクセスすると、対応する物理メモリページが割り当てられていないので、割り込みが発生し、カーネルによってページインが実行されます。そして、 /dev/zero のオフセット 1.2Gb の1ページが読み込まれますが、このデバイスは擬似デバイスなので、単に0の連続を1ページ分返すだけです。
この動作が終わった段階で物理メモリの消費は1ページです。ちなみにこのページに書き込むと /dev/zero に対するマッピングは解除されて、新しいメモリにコピーされ、そのメモリは swap 上の新しい1ページに対応付けられます(ここも詳細はもう少し難しい)。これを copy on write といいます。

10億個の配列を使用した場合、12x10^9になるので、メモリは12GB搭載していないと動かない・・・ということでしょうか?

上記の通りですので、メモリは12GB搭載してなくても動きます。しかし、 swap は 12GB 割り当ててないと動きません(これも厳密にはオーバコミットがあるので、ちょっと違う)。

注意)データセグメント、テキストセグメントはリンカ、ローダの用語であり、いわゆるメモリのセグメンテーションとは無関係です。

投稿2016/09/26 12:49

mit0223

総合スコア3401

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2016/09/26 12:54

ほああああああああ! すごいです。 何者ですの?? そのあたりについてもっと調べてみますね。 ありがとうございます!!
guest

0

その辺はOSによるところもありますが、多くの場合はお考えの通りだと思います。もちろん、文法上に誤りがないとしても物理的にメモリは有限ですし、仮想化していたとしても限界はどこかにあります。

ただ、具体的に「どれくらいあればいいか?」というのを数字で答えることは簡単ではありません。仮想化していれば二次記憶を事実上使うことができますし、逆にOSやコンパイラの制約でハードウェア資源以上に厳しい条件が課されることもあります。

投稿2016/09/26 12:29

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2016/09/26 12:31

そうですか。 わかりました。 OS理解のためのご助力に感謝いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問