【Rust】メモリ管理(スタックとヒープ)
ずっとJavaScriptを書いてきた身からすると、メモリ管理という単語はあまり触れたくない単語。
ブラウザのガベージコレクターが良い感じにやってくれるというくらいの認識しかなかった。
そこでRustに入門して、メモリ管理の第一歩を踏み出してみる。
Rustにはスタックとヒープという2種類のメモリ管理方法がある。
スタックとは
下から順に上に重ねていく方式。(last in, first out)
スコープが外れたタイミングで解放されていく。
fn next() { let y = 20; let z = 30; } fn main() { let x = 10; next(); }
上記の例では、main関数でx
のメモリが確保され、foo関数でy
, z
のメモリが確保される。
foo関数から抜けたタイミングでy
, z
はスコープ外となり、メモリが解放される。
そして、main関数が終わると全ての値が解放される。
スタックは単純な仕組みな故、高速である。
ヒープとは
順序関係なしにメモリ確保、解除ができる。
Box<T>
型を用いた場合はヒープ領域にメモリが確保されるようになっている。
スタックの時とは異なり、メモリ確保は一番後ろの番地から行われる。
ところで<T>
って何?
Rustのexampleを見ていると至る所に<T>
が出てくる。
これはジェネリック型というやつで、簡単に言えばどんな型でも柔軟に対応しますよという型。(間違ってたらすまん)
通常、TypeのTを取って<T>
と表記される場合がほとんどだが、別に何のアルファベットでも良いらしい。
話を戻しまして、
fn main() { let x = Box::new(5); let y = 10; }
上記の例の場合、Box::new(5)
によって生成された値はヒープ領域に保存され、x
はその番地へのポインタをスタック上で保持する。
main関数が終わり、x
がスタック上から解放されるタイミングでヒープ領域の値も解放される。
ヒープは自由度が高い故にコストが高く、スタックに比べると速度が遅い。
まとめ
基本的にはスタック形式でメモリ管理が行われるので、関数スコープを抜けたタイミングでメモリは解放されていく。
スコープを出てもメモリを保持したい場合にヒープを使うのだろうか。
まだ分からないことがたくさんあるので勉強せな。