メモリマップ

🔹 メモリマップとは?

👉 コンピュータのメモリ(RAM)のどこに、何が配置されているかを示した地図のようなもの

プログラムは実行時にメモリ上にロードされ、
「どの領域にコードが置かれるのか」「どの領域に変数が入るのか」
を管理する仕組みが メモリマップ です。


🔹 一般的なメモリマップ構造

多くの言語(C/C++やMQL4も内部的には似た仕組み)では、
メモリはおおまかに次のように分けられます👇

+-------------------------+ 高アドレス
| スタック (Stack)        | 関数の引数、ローカル変数
+-------------------------+
| ヒープ (Heap)           | 動的に確保したメモリ (new, malloc)
+-------------------------+
| データ領域 (Data)       | グローバル変数、static変数
+-------------------------+
| コード領域 (Text)       | 実行するプログラムの命令
+-------------------------+ 低アドレス

🔹 各領域の役割

  1. コード領域(Text segment)
    • プログラムの命令(コンパイルされた機械語)が入る場所
    • MQL4 なら、EAやインジケータのロジック部分
  2. データ領域(Data segment)
    • グローバル変数、static 変数など
    • プログラムの実行中ずっと残る
  3. ヒープ(Heap)
    • 動的に確保したメモリが置かれる領域
    • MQL4 では ArrayResize() などで配列サイズを増やしたときに内部的に利用される
  4. スタック(Stack)
    • 関数内で宣言したローカル変数
    • 関数を呼び出すたびに「積まれて」、終了すると「消える」
    • 例:int i=0; など

🔹 MQL4 に関連する例

MQL4では直接メモリ管理を意識することは少ないですが、
内部的には上記の仕組みを使っています。

  • グローバル変数
    → データ領域に置かれる
  • ローカル変数
    → スタックに積まれる(関数が終わると消える)
  • 動的配列(ArrayResize
    → ヒープ領域を利用して確保

🔹 イメージ図

メモリ(RAM)
 ┌──────────────┐ 高アドレス
 │ Stack        │ 関数内の変数 (一時的)
 ├──────────────┤
 │ Heap         │ 動的メモリ (ArrayResizeなど)
 ├──────────────┤
 │ Data Segment │ グローバル変数・static変数
 ├──────────────┤
 │ Text Segment │ プログラム本体 (EA/インジ)
 └──────────────┘ 低アドレス

✅ まとめ

  • メモリマップ = メモリをどう使うかの地図
  • 主に 4領域(コード / データ / ヒープ / スタック)に分かれる
  • MQL4 でも「グローバル変数=データ領域」「ローカル変数=スタック」「配列拡張=ヒープ」という形で関係している


🔹 1. 配列とメモリ

MQL4 の配列(double arr[]; など)は、
内部的には ヒープ領域 に置かれます。

  • ローカル変数(int i=0; など) → スタックに置かれる
  • グローバル変数(int g=0; など) → データ領域に置かれる
  • 配列(特にサイズ可変のもの) → ヒープに置かれる

👉 なぜかというと、配列は「大きさを変えられる」ため、スタックのように自動で確保できないからです。


🔹 2. 初期の状態(空配列)

double arr[];

宣言しただけの状態では、ヒープ領域に まだ何も確保されていません
このとき、ArraySize(arr)0 です。


🔹 3. ArrayResize() で確保

ArrayResize(arr, 3);

これで、ヒープに double型×3個分の領域 が確保されます。
メモリマップのイメージ👇

Stack (ローカル変数)
 ┌───────────────┐
 │ i=0            │
 └───────────────┘

Heap (配列などの動的領域)
 ┌───────────────┐
 │ arr[0]         │ → 0.0 (初期化)
 │ arr[1]         │ → 0.0
 │ arr[2]         │ → 0.0
 └───────────────┘

🔹 4. 要素数を増やす

ArrayResize(arr, 5);

今度は 5個分の領域 を確保しなおします。
このとき、

  • 以前の値は可能な限りコピーされる
  • 足りない分は初期値(0.0)で埋められる

イメージ👇

Heap
 ┌───────────────┐
 │ arr[0] → 0.0  │
 │ arr[1] → 0.0  │
 │ arr[2] → 0.0  │  ← ここまでは保持される
 │ arr[3] → 0.0  │  ← 新しく確保
 │ arr[4] → 0.0  │  ← 新しく確保
 └───────────────┘

🔹 5. 要素数を減らす

ArrayResize(arr, 2);

今度は 2個分だけ確保 し直します。
arr[2] 以降のデータは 消える(解放される) ので注意です。

Heap
 ┌───────────────┐
 │ arr[0] → 0.0  │
 │ arr[1] → 0.0  │
 └───────────────┘

🔹 6. まとめ

  • ArrayResize()ヒープ領域のメモリ確保・解放 を行う
  • 増やすとき → 既存のデータは残り、新しい部分は初期値で埋められる
  • 減らすとき → 範囲外のデータは消える

👉 これが「MQL4の配列とメモリマップの関係」です。


実用的な注意点

  • 頻繁に ArrayResize() すると、メモリの確保・コピーが多発して 処理が遅くなる
  • そのため「最大サイズを最初に確保しておき、使う部分だけ管理する」方法もよく使います


🔹 1. 通常の配列と価格配列の違い

  • 通常の配列(自分で宣言した配列)
    • 自分で double arr[]; と宣言する
    • ArrayResize() でサイズを変える
    • 値を入れるのも自分
  • 価格配列(Open[], Close[], High[], Low[], Time[], Volume[] など)
    • MQL4 が最初から用意している「システム配列」
    • チャートのローソク足データが自動で格納される
    • ArrayResize() 不要(自動的にサイズ調整される)
    • ユーザーが代入しなくても値が入っている

👉 つまり メタトレーダーが内部でメモリ管理してくれる特別な配列 なんです。


🔹 2. メモリマップのイメージ

MQL4 プログラムが動くときのメモリ配置をざっくり図にすると👇

Stack (ローカル変数)
 ┌──────────────┐
 │ i, j, k       │
 │ price[100]    │
 └──────────────┘

Heap (動的配列)
 ┌──────────────┐
 │ arr[0..N]     │
 └──────────────┘

System Data (MetaTraderが管理)
 ┌──────────────┐
 │ Close[]       │ ← チャートの終値データが格納済み
 │ Open[]        │ ← 始値
 │ High[]        │ ← 高値
 │ Low[]         │ ← 安値
 │ Time[]        │ ← 足の時間
 │ Volume[]      │ ← 出来高
 └──────────────┘

通常の配列はプログラム側で管理する必要がありますが、
価格配列はMT4ターミナルが勝手に埋めてくれる 特殊領域です。


🔹 3. ArraySetAsSeries() が必要な理由

価格配列のインデックスは少しクセがあります。

  • デフォルト:
    • Close[0]最古の足
    • Close[Bars-1]最新の足
  • ArraySetAsSeries(Close, true); をすると:
    • Close[0]最新の足
    • Close[1] → 1本前
    • Close[2] → 2本前 …

👉 普通は「最新足を [0] にした方が分かりやすい」ので、ArraySetAsSeries() を使うのが一般的。


🔹 4. 実例:昨日の高値・安値を取る

void OnTick()
{
   // 配列を「最新を0番」にする
   ArraySetAsSeries(High, true);
   ArraySetAsSeries(Low, true);

   double yHigh = High[1];  // 昨日の高値
   double yLow  = Low[1];   // 昨日の安値

   Print("昨日の高値=", yHigh, " 昨日の安値=", yLow);
}

このように、価格配列は「チャートのデータベース」に直結していて、
自分で ArrayResize したり for文で埋めたり しなくてもすぐに使えます。


🔹 5. まとめ

  • 価格配列(Close[], Open[] …)は MetaTraderが内部で管理している特別な配列
  • 自動でメモリ確保され、チャートのローソク足データが常に入っている
  • ArraySetAsSeries() を使うと「最新足を [0]」にできるので便利
  • 自分で確保する普通の配列とは扱いが違う

コメント

タイトルとURLをコピーしました