Rust, 메모리 레이아웃과 다형성의 비밀을 파헤치다!

by DD
5개월 전
조회수 3

C/C++와 달리 Rust는 컴파일러가 필드 순서를 재정렬하여 메모리 사용량을 최적화함.

repr(C)를 통해 C 호환 레이아웃을 지원하며, FFI 및 특정 메모리 구조에 대한 안정성을 제공함.

DST(Dynamically Sized Types), Fat Pointer, Vtable을 활용한 다형성 구현은 성능 트레이드 오프를 수반함.

Rust의 메모리 레이아웃 알고리즘

Rust는 기본적으로 repr(Rust)를 사용하여 필드 순서를 컴파일러가 최적화하도록 한다. 구체적으로, 패딩을 최소화하기 위해 필드 순서를 재정렬하며, 이는 메모리 사용량을 줄이는 데 기여한다. 따라서, FFI(Foreign Function Interface)를 위해 repr(C)를 사용하면 C와 호환되는 레이아웃을 보장하며, 바이너리 호환성을 확보한다.

다형성 구현: Vtable vs Monomorphization

Rust는 Trait Object를 통해 다형성을 구현하며, 이는 Vtable을 사용한 동적 디스패치를 통해 이루어진다. 구체적으로, Vtable은 각 타입별로 함수 포인터를 저장하여 런타임에 적절한 함수를 호출한다. 반면, Monomorphization은 컴파일 타임에 각 타입에 대한 코드를 생성하여 성능을 향상시키지만, 코드 중복을 발생시킬 수 있다.

DST(Dynamically Sized Types)와 Fat Pointer

Rust는 DST를 사용하여 런타임에 크기가 결정되는 타입을 지원하며, SliceTrait Object가 대표적이다. 따라서, Fat Pointer는 데이터에 대한 포인터와 추가적인 메타데이터(예: 길이, Vtable)를 포함한다. 결과적으로, Unsizing Coercion을 통해 &[T]와 같은 DST에 대한 안전한 접근을 보장하며, 버퍼 오버플로우 문제를 해결한다.

Who Owns the Memory? Part 3: How Big Is your Type?