rust 라이프타임

wangki·2025년 7월 11일
0

Rust

목록 보기
37/54

개요

lifetime이 이렇게도 쓰이는지 알게되어 작성해본다.

내용

#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
    F: FnOnce() -> T,
    F: Send + 'static,
    T: Send + 'static,
{
    Builder::new().spawn(f).expect("failed to spawn thread")
}

위 코드는 std::thread::spawn 함수의 정의 부분이다.
자세히 보면 타입을 정의하는 곳에 'static이 붙은 것을 볼 수 있다. 이것은 라이프타임의 문법으로 보통 &'static str 이런 식으로 사용된다. 그렇다면 여기서 이것이 쓰이는 진짜 의미가 뭔지 알아보겠다.

F: Send + 'static 여기서 'static은 타입 F가 어떤 참조도 포함하고 있지 않거나, 만약 포함하고 있다면 그 모든 참조들은 적어도 'static 라이프타임을 가져야 한다는 의미이다.

스레드의 경우 실행 순서가 보장되지 않고, 언제 시작해서 언제 끝날지 예측이 어렵다. 클로저가 특정 변수를 캡처하였는데 이후 해당 스레드가 호출이 되면서 클로저가 실행될 때 캡처한 변수가 가르키는 값이 이미 사라져있을 수 있다. 따라서 이런 상황을 방지하기 위해서 'static라는 제약을 걸어주는 것이다.

예제 코드

fn test_func<T>(x: T) 
where 
    T: std::fmt::Display + 'static
{
   println!("{}", x);
}

fn main() {
    let winter = "winter";     
    test_func(winter);
    
    let name = "카리나".to_string();
    let ref_name = name.as_str();
    test_func(ref_name);
}

위 예제의 경우 test_func함수가 제네릭 타입을 매개변수로 받고 트레이트 바운드가 std::fmt::Display를 구현하여 출력을 할 수 있도록 하였고, 'static을 추가해줘서 타입 T가 참조 값을 가지고 있지 않거나, 가지고 있더라도 'static 참조를 가지고 있어야 한다는 제약을 걸었다.

main함수에서는 winter라는 변수를 만들어서 'static str타입으로 만들어주었고 test_func의 매개변수로 넘겨 주었다. 이상이 없었다. 그러나 ref_name의 경우에 name을 참조하고 있는 참조 변수이고 test_func의 매개변수로 넘겨주었을 때 라이프타임이 'static이 아니기 때문에 에러가 발생했다.

결론

타입을 정의할 때 라이프 타임이 사용될 수 있는 것을 알았다. 라이브러리들을 보면 트레이트 바운드가 복잡하게 설정된 경우가 있었는데 이전보다는 더 쉽게 볼 수 있을 것 같다.

0개의 댓글