RustRoverのMemory ViewでRustのメモリを確認
最近よくRustを書いていて、IDEには慣れているJetBrainsのRustRoverを利用している。1 RustRoverにはMemory view機能があるため、これを利用してRustのオブジェクトのメモリ構造を確認してみた。
実行するコード
use std::mem::size_of_val;
use std::slice::from_raw_parts;
fn main() {
let words = vec!["spam", "ham", "egg"];
let p = words.as_ptr();
unsafe {
println!("p = {:?}", p);
println!("*p = {:?}", *p);
}
println!("words = {:?}", as_raw_bytes(&words));
println!("break here"); // ここにブレークポイントを設定してデバッグ実行
}
// https://qnighy.hatenablog.com/entry/2017/03/04/131311
// https://cipepser.hatenablog.com/entry/rust-memory
fn as_raw_bytes<T: ?Sized>(x: &T) -> &[u8] {
unsafe { from_raw_parts(x as *const T as *const u8, size_of_val(x)) }
}
コード中にもコメントしていますが、関数as_raw_bytes()
は下記を見て知ったものです。
実行
ブレークポイントで停止したら、println!()
の結果がConsoleタブに出力されている。
Memory View機能で確認
Threads & Variablesタブ。
Threads & Variablesタブで各変数を右クリックすると、「Show in Memory View」からMemory Viewの該当アドレスにジャンプできる。
Vecのメモリの内容はConsoleに出力されていた words =
の値と一致。
Vecはbufとlenから構成されており、bufはptrとcapから構成されている。
つまりVecは3つのusizeから構成されている。
また、ptr部分の値0x00006000012500c0
はConsoleに出ていた p =
の値と一致。
このアドレスに入っている値は0x0000000100c429ac 0x0000000000000004
。
この値はstr
を参照している&str
型。つまりこれもアドレスと文字列長len。
アドレス0x0000000100c429ac
に入っている値を確認すると、spam
の文字列 = 73 70 61 6d
を発見。
おまけ。
メモリビュー見るときはいつもPythonのREPLを使っている気がする。 サクッと変換できるのはやはり便利。ASCIIの範囲くらいは覚えておきたいけど。
$ python3 -q
>>> for c in 'spam':
... print(f"{ord(c):02x} ", end="")
...
73 70 61 6d
感想
Memory View上の値を選択して、アドレスとしてジャンプできる機能が欲しい。 いつか実装されることを望んでいる。
-
PyCharmは10年くらい課金している気がする。ここ数年はAll Products Packユーザー。 ↩