1.4. raw allocation - alloc / dealloc / realloc
rok::bare::alloc 모듈은 GC 가 관여하지 않는 외부 영역에서 메모리를 직접 할당하고 해제하기 위한 API 를 제공합니다. rok 의 일반 코드는 GC 가 알아서 관리해 주지만, FFI 경계에서 C 측에 메모리를 넘겨야 하거나 large buffer, mmap 처럼 GC 가 다루기에 적절치 않은 자리에서는 이 모듈을 사용합니다.
1.4.1. API
struct Layout {
size: usize;
align: usize;
}
impl Layout {
fn new<T>() -> Layout; // size_of<T>(), align_of<T>()
fn array<T>(n: usize) throws (LayoutError) -> Layout;
fn from_size_align(size: usize, align: usize) throws (LayoutError) -> Layout;
}
unsafe fn alloc(layout: Layout) -> CPtr<u8>;
unsafe fn alloc_zeroed(layout: Layout) -> CPtr<u8>;
unsafe fn dealloc(ptr: Ptr<u8>, layout: Layout);
unsafe fn realloc(ptr: Ptr<u8>, old_layout: Layout, new_size: usize) -> CPtr<u8>;
// 편의 함수 - typed
unsafe fn alloc_one<T>() -> CPtr<T>;
unsafe fn alloc_array<T>(n: usize) -> CPtr<T>;
unsafe fn dealloc_one<T>(ptr: Ptr<T>);
unsafe fn dealloc_array<T>(ptr: Ptr<T>, n: usize);
alloc 이 실패하면 CPtr::null() 을 반환하며, abort 하지 않으니 호출자가 직접 결과를 살펴 처리해야 합니다.
1.4.2. 사용 예
let layout = try Layout::array::<u32>(1000);
let p: CPtr<u8> = unsafe { rok::bare::alloc::alloc(layout) };
match p.as_ptr() {
raw: Ptr<u8> => {
let typed: Ptr<u32> = rok::bare::ptr_cast::<u32>(raw);
// 사용
unsafe {
for i in 0u32..1000u32 { typed.add(i as usize).write(i); }
}
unsafe { rok::bare::alloc::dealloc(raw, layout) };
}
none => panic("alloc failed"),
}
using 블록을 활용하면 RAII 형태로 정리할 수 있습니다.
using buf = try rok::bare::alloc::Allocation::<u32>::new(1000) {
// buf.as_ptr() 사용 가능
} // ← 자동 dealloc
여기서 Allocation<T> 는 본 모듈에 포함된 RAII wrapper 입니다.
1.4.3. GC 와의 관계
| 영역 | 할당 / 해제 | GC 관리? |
|---|---|---|
일반 객체 (List<i32>) | GC TLAB bump | ✓ |
rok::bare::alloc::alloc | system malloc | ✗ (수동) |
FFI malloc | C malloc | ✗ |
| Large object (≥8KB) | LOS - non-moving mark-sweep | ✓ (단, non-moving) |
GC 가 관리하는 raw buffer 가 필요하면 이 모듈 대신 rok::core::collections::raw::GcBuf<T> (2.9.12) 를 씁니다.
GC 외부 영역은 GC 의 추적 대상이 아니므로 정리 책임이 사용자에게 있습니다. 다만 객체가 이동하지 않는 영역인 만큼, Ptr<T> 는 별도의 pin guard 없이도 그대로 유효합니다.
1.4.4. runtime 연계
rok::bare::alloc::alloc 의 본문은 rok 런타임이 system malloc 위에 제공하는 wrapper 로 lower 되며, 최종적으로 libc::malloc / libc::free / libc::realloc 을 호출하는 형태로 동작합니다.