alloc

allocを使うためには、グローバル(ヒープ)アロケータを実装しなければなりません。

#![no_main]
#![no_std]

extern crate alloc;
extern crate panic_halt as _;

use alloc::string::ToString;
use alloc::vec::Vec;
use buddy_system_allocator::LockedHeap;

#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();

static mut HEAP: [u8; 65536] = [0; 65536];

pub fn entry() {
    // SAFETY: `HEAP` is only used here and `entry` is only called once.
    unsafe {
        // アロケーターにメモリを割り当てます。
        HEAP_ALLOCATOR.lock().init(HEAP.as_mut_ptr() as usize, HEAP.len());
    }

    // これで、ヒープ割り当てを必要とする処理を実行できるようになりました。
    let mut v = Vec::new();
    v.push("A string".to_string());
}
  • buddy_system_allocatorはサードパーティのクレートで、単純なバディシステムアロケータです。その他にも利用できるクレートはありますし、自前で実装したり、別のアロケータに自分のコードをフックすることも可能です。
  • パラメータ定数LockedHeapはアロケータの最大オーダを示します。この場合、2**32バイトの領域を確保することが可能です。
  • もし依存関係にあるクレートがallocに依存する場合、必ずバイナリファイルあたり一つだけのグローバルなアロケータが存在するようにしなければなりません。通常、これはトップレベルのバイナリを生成するクレートにより制御されます。
  • extern crate panic_halt as _ という部分は、panic_haltクレートを確実にリンクし、パニックハンドラを利用可能にするために必要です。
  • この例で示したコードはビルドできますが、エントリポイントがないので実行することはできません。