このページの目次
アロケータとメモリレイアウト
Rust はデフォルトでシステムの malloc/free を使用しますが、GlobalAlloc トレイトを実装してグローバルアロケータを置き換えたり、特定コンテナにカスタムアロケータを指定したりできます。Layout はメモリサイズとアライメントを記述し、Pin は値の移動を防止します(自己参照型や非同期 Future に不可欠)。
#[repr(align)]および#[repr(C)]によりメモリレイアウトを精密に制御できます。
デフォルトアロケータ
Rust はデフォルトでシステムの malloc/free(Linux では glibc の ptmalloc2)を使用しますが、置き換えることができます。GlobalAlloc トレイトを実装し、#[global_allocator] でマークします:
use ;
;
unsafe
static GLOBAL: MyAllocator = MyAllocator;
一般的な代替アロケータ:mimalloc(Microsoft、フラグメンテーションが低い)、jemalloc(FreeBSD、マルチスレッド最適化済み)、snmalloc(Microsoft Research、メッセージパッシングベース)。
Layout: 割り当てリクエストの記述
アロケータは直接「N バイトください」というリクエストを受け取るのではなく、サイズとアライメントを含む Layout 構造体を受け取ります:
use Layout;
let layout = ; // size=8, align=8
let layout2 = from_size_align.unwrap;
アロケータは、アライメント要件を満たすメモリを返さなければなりません。割り当てに失敗した場合は、null を返します(パニックしません)。
allocator API: 手動割り当て
use ;
let layout = ;
let ptr = unsafe ;
unsafe ;
unsafe ;
これは、型安全な Layout パラメータが追加された C の malloc/free にほぼ相当します。ほとんどのコードでは alloc を直接呼び出す必要はありません。Box、Vec、String などが既に処理してくれます。
Pin: 移動の防止
Rust のムーブセマンティクスでは、任意の値が新しいアドレスに memcpy される可能性があります。しかし、自己参照構造体(struct のフィールドが同じ struct の別のフィールドを参照している場合)では、ムーブ後に参照がダングリングになります。Pin は、ピン留めされた値がそれ以上ムーブされないことを保証します:
use Pin;
// 典型的な自己参照構造体(簡略化版):
// 構築時に ptr は value を指しますが、SelfRef がムーブされると → ptr がダングリングする
// Pin<Box<SelfRef>> は SelfRef がムーブされないことを保証し、安全です
async fn から生成される Future は典型的な自己参照構造体です。これは、await ポイントより前のローカル変数を参照します。Pin<&mut Future> は、poll 中に Future がムーブされないことを保証します。これが async/await コンパイラの内部実装の基盤です。
参考
- Rustonomicon: アロケータ、Pin
- RFC 1398: カスタムアロケータ
- RFC 2349: Pin
Keywords: GlobalAlloc, Layout, custom allocator, Pin, self-referential, #[repr(align)], alloc API