🔹 メモリマップとは?
👉 コンピュータのメモリ(RAM)のどこに、何が配置されているかを示した地図のようなもの
プログラムは実行時にメモリ上にロードされ、
「どの領域にコードが置かれるのか」「どの領域に変数が入るのか」
を管理する仕組みが メモリマップ です。
🔹 一般的なメモリマップ構造
多くの言語(C/C++やMQL4も内部的には似た仕組み)では、
メモリはおおまかに次のように分けられます👇
+-------------------------+ 高アドレス
| スタック (Stack) | 関数の引数、ローカル変数
+-------------------------+
| ヒープ (Heap) | 動的に確保したメモリ (new, malloc)
+-------------------------+
| データ領域 (Data) | グローバル変数、static変数
+-------------------------+
| コード領域 (Text) | 実行するプログラムの命令
+-------------------------+ 低アドレス
🔹 各領域の役割
- コード領域(Text segment)
- プログラムの命令(コンパイルされた機械語)が入る場所
- MQL4 なら、EAやインジケータのロジック部分
- データ領域(Data segment)
- グローバル変数、
static
変数など - プログラムの実行中ずっと残る
- グローバル変数、
- ヒープ(Heap)
- 動的に確保したメモリが置かれる領域
- MQL4 では
ArrayResize()
などで配列サイズを増やしたときに内部的に利用される
- スタック(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]」にできるので便利- 自分で確保する普通の配列とは扱いが違う
コメント