rust 객체 안전성 보장

wangki·2025년 7월 11일
0

Rust

목록 보기
36/54

개요

Box<dyn Trait>인 Trait 객체를 만들기 위해서는 객체 안전성을 지켜야 한다.
즉, 트레이트 메서드가 반드시 self 매개변수를 가져야 한다는 중요한 규칙이 있다. 이 규칙을 지켜야만 vtable을 통해 올바른 메서드 호출을 동적으로 디스패치할 수 있다.

내용

trait Drawable {
    fn draw();
}


#[derive(Default)]
struct Button;

impl Drawable for Button {
    fn draw() {
        println!("Button draw!");
    }
}

#[derive(Default)]
struct Toggle;

impl Drawable for Toggle {
    fn draw() {
        println!("Toggle draw!");
    }
}

fn main() {
    let drawable_list: Vec<Box<dyn Drawable>> = Vec::new();
}

위와 같은 코드가 있다. traitDrawabledraw라는 연관 함수를 만들었다.
ButtonToggle 구조체를 만들어 각각 Drawable을 구현했다. main에서 사용하려고 하는데 오류가 발생하였다.

이 에러 메시지의 의미는 해당 트레이트가 동적 디스패치에 적합하지 않다는 의미이다. 이것은 객체 안전성 규칙을 위반했기 때문에 발생한다.

왜 문제가 되는가?

트레이트 객체의 경우 동적으로 생성 시 vtable을 가리키는 포인터를 가진다. 이때 트레이트 메서드가 self를 가지고 있지 않다면 vtable에 포함될 수 없기 때문에 트레이트 객체를 만들 수 없다.

정상 동작 시키기

trait Drawable {
    fn draw(&self);
}


#[derive(Default)]
struct Button;

impl Drawable for Button {
    fn draw(&self) {
        println!("Button draw!");
    }
}

#[derive(Default)]
struct Toggle;

impl Drawable for Toggle {
    fn draw(&self) {
        println!("Toggle draw!");
    }
}

fn main() {
    let drawable_list: Vec<Box<dyn Drawable>> = vec![Box::new(Button::default()), Box::new(Toggle::default())];

    for draw_obj in drawable_list {
        draw_obj.draw();
    }
}

정상적으로 출력이 되는 것을 볼 수 있다.
main함수가 호출이 되면서 런타임에 동적으로 트레이트 객체가 생성이 된다.

결론

rust를 사용하여 개발하며 Box<dyn >으로 동적 디스패치를 하기는 했지만 정확히 어떻게 동작하는지 몰랐는데 이번 기회를 통해서 좀 더 깊이 있게 알게 된 것 같다.

0개의 댓글