メモリ増加に関する疑問

このQ&Aのポイント
  • static変数で大きな配列を取得し、任意の位置に値を入れると、メモリ使用量が増える
  • C言語ではメモリをリニアに取得するが、拡張子や環境により異なるように見える
  • メモリダンプで確認すると、使用メモリの増加が確認できる
回答を見る
  • ベストアンサー

メモリの増加に関して

static 変数にて 大きな配列を取得し、その配列の任意の位置(サンプルでは4k毎) に値を入れた場合、 タスクマネージャのプロセスでメモリ使用量を確認した場合、ステップ実行毎にメモリが増えて行くように見受けられます。 本来C言語なら 実行時にリニアにメモリを取得するとの認識ですが、拡張子がcpp だからか、windows環境だからなのか? 色々と理解できません。 また、4k毎と記載しておりますが、どうも4k毎にメモリを取得しているように見受けられるためにその様に記載いたしました。 しかしメモリダンプで見た場合、リニアに見えていることを考慮すると。 空間的には指定のサイズ分リニアなメモリを用意する(他のメモリとはオーバーラップしない) 使用時に実使用メモリとして管理(カウント)する。 等の動きをしているのでしょうか? メモリダンプでアドレスをずらしながら確認すると使用メモリの増加が確認できております。 ファイル拡張子をcに変更して、プリプロセッサの設定を変更しても同じ現象の確認が取れました。 大きなメモリを使うのだからmallocを、、、は 今回は無しでお願いします。 純粋になぜこのような動きになっているかを知りたいと思っております。 よろしくお願いします。 OS XP SP3 開発環境 VC2005 ファイル拡張子 cpp コンソールアプリ /***************************************/ #include "stdafx.h" #define WORK_STATIC_MOMOERY_SZ ( 10 * 1024 * 1024 ) static char work_static_momory[WORK_STATIC_MOMOERY_SZ]; int _tmain(int argc, _TCHAR* argv[]) { work_static_momory[0] = 0x12; work_static_momory[ 4 * 1024 ] = 0x12; work_static_momory[ 8 * 1024 ] = 0x12; work_static_momory[12 * 1024 ] = 0x12; work_static_momory[16 * 1024 ] = 0x12; return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
noname#208124
noname#208124
回答No.1

それはもう言語を越えたCPUとOSの実装の話になります C言語での静的変数は確かに仮想メモリ内では全て確保済みに見えます しかしOSは全部まとめてゼロページという内容が全部0の物理メモリに結びつけます だって言語規格的にも0ですから 書き込まれるまでの読み取りは0が返ればいいんです 書き込みが起きたときにそれを検知し初めてOSはメモリを確保してその物理メモリをプロセスの仮想メモリに結びつけます この仕組みはdemand zero faultとかDemand Pagingとか呼ばれますがやっているのはWindowsだけじゃありません 必要になるまでメモリの確保要りませんから起動の高速化などの利点がありますからサーバー用途、デスクトップ用途のOSはみんなやってます 次に仮想メモリと物理メモリを結びつける仕組みとしてページング方式ってのがあります 1バイト毎に結びつけると管理領域が馬鹿にならないのでOSとCPUはこれをいくらかまとめて管理します これをページと呼び、普通のWindowsが動くx86 CPUでは通常は4KBを1ページとして管理します ページ毎に管理している以上仮想メモリに結びつけたらその1ページサイズの物理メモリは確保済みになります なのでwork_static_momory[0]に書き込みを行ったらwork_static_momory[4095]まではメモリの確保は行われません

xionggu
質問者

お礼

回答ありがとうございます。 OS介在の話になるわけなんですね。 アセンブラにて確認しても理解できなかったのが事実なのですが、 OSはアセンブラプログラムをエミュレートして動作させていると いうことなんですね。WindowsOSは何処まで何をしているかとても 興味深く感じております。

関連するQ&A

  • malloc メモリリークについて

    #include<stdio.h> #include<stdlib.h> void alloconly(void) { const int sz=10; static int n=0; void *p; p=(void*)malloc(sz); if(p==NULL){ printf("動的確保不可 %d\n",n+1); printf("確保メモリサイズ %d byte\n",sz*n); exit(-1); } ++n; } int main(void) { for(;;){ alloconly(); } }と言うプログラムがある本に載っており、回答として   動的確保不可 *******(数字)   確保メモリサイズ *********byte(数字)となっていますが私の環境(Reshat Linux)では   強制終了します で終了してしまいます。原因が判らず困っています。ご解答願います。

  • 汎用機COBOLのメモリ管理について

    汎用機COBOLのオンラインPGですが、明細データをDBから読み込んで、配列に入れていますが、99%は300件以下です。1%は300件以上ですが、その場合1000件以上になります。そこで、通常は300の配列で処理をし、300件を超えたら1100の配列で処理をする様にして、メモリの使用を抑えようとしています。この場合、可変長配列を使用すれば、何の問題も無いのですが、自分が配属された時には、2つの固定長配列のCOPY句を使用して、目的を達成しようとしていました。方法は、 (1)配列300のCOPY句をワークエリアに、配列1100のCOPY句をリンケージエリアに配置する。リンケージエリアにCOPY句を配置する理由は、何もしなければ、メモリを消費しないからです。 (2)配列300のワークエリアを初期化して、そのアドレスをリンケージエリアの配列1100にセットする。この時点では、ワークエリアとリンケージエリアで配列300分のメモリアドレスを共有する。 (3)共通サブルーチンに(2)のアドレスを渡し、明細を取り込む。1100を超えた場合は、アドレスを取り直して、返却する。 (4)メインPG側で、返却されたアドレスをリンケージエリアの配列1100のエリアにセットし直す。 (5)判定や計算をする場合は、リンケージエリアの配列1100の項目名を使用する。 以上が、大まかな処理の流れです。 そこで、疑問なのが明細が300件未満の場合です。使用しているメモリの場所は、ワークエリアの配列300とリンケージエリアの配列1100とは、同じワークエリアのメモリアドレスになるので、どちらのCOPY句で処理しても、同じ結果になります。この時、配列300分のメモリしか使用していない事になっていますが、判定や計算には配列1100の項目名を使用しています。そこで疑問なのは、アドレスセットだけなら問題無いにしても、配列1100の項目を処理に使用した時点で、配列1100分のメモリが確保されてしまうのではないかという事です。つまり、節約しているつもりが、配列1400分のメモリを浪費しているのではないかという疑問です。配列300の場合と配列1100の場合とで、PGを完全に二重化すれば問題は無いとおもいますが、メーカーの担当エンジニアは問題無いと言っているのですが、誤解が有るような気がしてなりません。どなたか、解る方がいらっしゃいましたら、ご教示頂けると幸いです。どうぞよろしくお願い致します。

  • メモリの初期値

    C言語の勉強をしている者です。 やっとこさポインタのところまでやってきまして、いろいろ試しているところなのですが、不可解な事が起こったので質問させてください。 int型の配列を作って、初期化しないままその配列[0]に入っている値を覗くと -858993460 という値が入っていました。 もう一度配列を作り、メモリのアドレスを確認すると、前に作った配列とポインタのアドレスが同じだったので そこに0を入れました。 当たり前ですが配列[0]の値は0でした。 さらにもう一度配列を作り、[0]のアドレスの中身を覗くと -858993460 という値に戻っていました ※配列[0]のアドレスは常に一緒です。 なぜこんな訳のわからない数字( -858993460 )に初期化されているんでしょうか 一度0に初期化したのなら次は0のままになっていると予測していたのですが、どうなっているんでしょうか どなたか理由のわかる方いませんか

  • 多次元配列のデータ個数やメモリについて

    今,2次元配列で, static double g[20000][10] として,配列を使用することを考えています。(他にも一次元配列を多くあります)これを使って計算を行います。 g[20000][9]の場合は正常に動いたんですが,g[20000][10]にするとaccess violation(アクセス違反)のように出ます。メモリの問題でしょうか,それとも限界なんでしょうか,,,,? この解決策はありますか?よろしくお願いします。 Visual C++6.0 で動作

  • ノートPCのメモリ増設について教えてください。

    ノートPCのメモリ増設について教えてください。 VAIOのVGN-SZ92Sを使用しており、複数のソフトを立ち上げたときに重さを感じるのでメモリの増設を考えております。(現在は、1.5GBのメモリを使用しています。) BUFFALOのHPで確認すると、3GBまでいけるそうなのですが、実際メモリを倍にしたときの効果を教えていただけますでしょうか? スピード等目覚しく変わるのでしょうか? よろしくお願い致します。

  • メモリの入れ替えを予定していますが・・・

    [備考] メモリ規格: PC3200 184pin DDR SDRAM DIMM nonECC スロット数: 2 最大容量: 1GB 現状はデフォのMicron 256MBx1が挿さりっ放しなので フル拡張するには、512MBx2への交換となりますよね。 ここまでは解かっているのですが・・・ メモリメーカーで機種から検索すると、拡張2GBまでの動作が 確認されているようです。この場合、1GBx2が前提であって x1では動かないと言う意味なのでしょうか? わからないので教えて下さい!

  • static宣言について

    現在、c言語とDXライブラリを使ってゲームを製作しています。 http://okwave.jp/qa/q8270456.html 前回、このような質問をさせていただき、原因らしき箇所を突き止める所までいきました。 と言いますのも、配列の要素を指定する箇所(分かり辛かったらすいません。要素数ではありません)に、static宣言された変数を入れるとなぜかプログラムが強制終了されてしまうのです。 加えて、DXライブラリのGetColor関数にも返ってきた色をStatic宣言された変数に格納すると、何故か指定された色と違う色が出てしまうことが分かりました。 なんとか、その関数が終わる度に値を格納したかったので、色々試しました。 直接Static宣言されていない変数を間に噛ませてみたり、同じcpp内にわざわざ別の関数を用意して、そちらでStatic宣言し、値を返してみたり、と色々とやったのですが上手くいきませんでした。 ****************************************** int hairetu[20]; Static int z = 0; int x = z-1+1 hairetu[x] = zahyouX; (static宣言された変数zでhairetu[]の[]内を指定しようとするとダメ) (上記のように意味のない計算をさせてstatic宣言されていない変数を間にかませてもダメ) ****************************************** 結局の所、別のcppを用意して、ただ一つのStatic変数を+1していくだけの関数をくみ上げた所、上手くいったのですが・・・。何故このような事が起きるのでしょうか。 Static宣言された変数の決まりごと、もしくは、このような状態になってしまった原因など、見当がつきましたら教えていただけると有難いです。よろしくお願いします。

  • Android「メモリ」に作成したDBを確認したい

    Androidエミュレータで、 SQLiteを、「ストレージ」ではなく「メモリ」に作成した場合、 データベース内容を確認する方法はあるでしょうか? ※dumpデータ取得したり、selectで中身を見たいです 「メモリ」指定すると駄目なのでしょうか? 「メモリ」ってそもそもどこにあるのでしょうか? 「エミュレータイメージファイル」のどっか奥に、変換して保存されているのでしょうか?

    • ベストアンサー
    • Java
  • Windowsのダンプについて教えてください。

    【至急】 急なお願いで申し訳ございません。 以下2つの質問について、教えていただけますでしょうか。 1)以下、ダンプの違いについて詳しく、教えてください。 ・ユーザーダンプ ・プロセスダンプ ・メモリダンプ(完全メモリダンプ) ・カーネルダンプ ・クラッシュダンプ 2)また、プロセスID(PID)を指定してダンプを取得した場合、 どのダンプであれば、プロセスが消えるまで取得できるのでしょうか。 なお、ADPulsを使用しダンプの取得は出来たのですが、 上記のどのダンプの種類に当てはまるのか不明でした。 ADPulsで取得したダンプの種類もわかる方がいらっしゃれば、 併せて、教えていただければ幸いです。

  • XPでのメモリダンプファイル作成時のキー割当について

    こんにちは。 以下の事柄で困っています。お知恵を貸してください。 やりたいことは、WindowsXP(SP2/SP3)環境にて、メモリダンプを取得したいと考えています。 http://support.microsoft.com/kb/244139/ja こちらのサイトを参考に、レジストリを変更しCtrl+ScrollLock 2回でダンプファイルが取得できることを確認しました。 ですが、Ctrl+ScrollLock 2回以外のキーを割り当てて、同じ動作をさせたいのですがやり方がわかりません。 前述のサイトに「メモリ ダンプ ファイルを生成するキーの構成」と言う項目が有りましたので、レジストリをDump1Keys=0x01,Dump2Key=0x39として再起動してみたのですが(その際、CrashOnCtrlScroll の値は1のままにしています)、Shift(右)+Space2回ではダンプファイルは取得できず、先ほどと同じCtrl+ScrollLock 2回にて取得できました。 他に何か設定が必要なのでしょうか? (念のため、CrashOnCtrlScrollのレジストリを削除した状態でも試しましたが、ブルースクリーンにはなりませんでした) 色々と調べてみたのですが、原因が判明していません。 私のやろうとしている事が、可能かどうかだけでも回答いただければありがたいです。