Rustにおいて、アロケータは動的メモリ(ヒープ)の割り当てと解放を担当します。デフォルトでは、Rustは標準のシステムアロケータを使用していますが、言語はグローバルおよびローカルインターフェースを通じてユーザー定義のアロケータを使用する機会を提供しています。これは以下の理由で必要になることがあります:
バージョン1.28以降、グローバルアロケータは属性#[global_allocator]を使用して設定されます:
use std::alloc::System; #[global_allocator] static GLOBAL: System = System;
独自のアロケータを作成するには、std::allocからのトレイトを実装します:
use std::alloc::{GlobalAlloc, Layout}; struct MyAlloc; unsafe impl GlobalAlloc for MyAlloc { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { // ここに割り当てロジック std::alloc::System.alloc(layout) // 委譲する } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { // 解放ロジック std::alloc::System.dealloc(ptr, layout) } } #[global_allocator] static GLOBAL: MyAlloc = MyAlloc;
質問: ランタイム中にグローバルアロケータを変更できますか?例えば、条件や設定に応じて。
回答: いいえ!グローバルアロケータはコンパイル時に選択され、#[global_allocator]を通じて静的に設定されます。ランタイム中に変更することはできず、動的に選択することもできません。この属性はコンパイル時に生成されたコードに影響を与えるためです。
物語
Box::newでセグメンテーションフォルトを引き起こしました。静的メモリプールへのアクセスを持つ独自のアロケータの実装が役立ちました。物語
物語
デスクトップアプリケーションの開発中に、サードパーティのアロケータjemallocを使用しましたが、rustcのバージョン間でのABIの違いを考慮していませんでした。これにより、データのシリアライズ時に捕らえにくいクラッシュが発生しました。なぜなら、異なるコードの部分が異なるメモリ割り当ての合意を期待していたためです。