Rust

[Rust] 메모리 관리, 소유권 규칙 정리

차노도리 2024. 4. 14. 21:06

https://www.rust-lang.org/

 

Rust Programming Language

A language empowering everyone to build reliable and efficient software.

www.rust-lang.org

 

Rust 메모리 관리

  • Rust는 가비지 컬렉터(GC)를 사용하지 않으면서도 안전한 메모리 관리를 수행한다.
  • 컴파일러가 소유권 규칙을 강제함으로써, 메모리 할당 및 해제를 자동으로 관리한다.
  • 개발자는 메모리 해제를 직접 처리할 필요가 없다.
  • 런타임 성능 저하 없이 메모리 안정성을 보장한다.

 

Rust 소유권 규칙

  • 모든 값은 소유자(owner)를 가지며, 한 시점에 단 하나의 소유자만이 존재할 수 있다.
  • 소유자가 스코프를 벗어나면, 그 값은 자동으로 해제된다.

 

Stack 영역

  • 컴파일 시점에 크기가 결정된다. 함수가 호출될 때 자동으로 할당되며, 함수가 종료될 때 자동으로 해제된다.
  • 기본 데이터 타입(정수, 부동 소수점, 불리언, 문자 등)과 고정된 크기를 가진 튜플(기본 데이터 타입으로만 구성된 경우)이 스택 영역에 저장된다.
  • 스택 영역에 저장된 데이터는 값이 복사되어 다른 변수에 할당될 때 원본 데이터 자체가 복사된다.

 

ex) Stack영역 소유권 이동이 되지 않고 데이터 복사 예시 

let x = 3;
let y = x;  // Stack 영역에 있는 데이터 복사 시, 데이터 자체가 복사되

println!("x ={}", x);   // 사용 가능
println!("y ={}", y);

 

 

Heap 영역

  • 런타임 시점에 크기가 결정되며, 동적으로 메모리가 할당된다.
  • 힙 영역의 데이터를 이동하거나 복사할 때는 소유권이 넘어가거나 명시적으로 clone()을 사용하여 데이터를 복사해야 한다.

 

ex) Heap 영역 소유권 이동 예시

let str1 = String::from("스트링 생성");
println!("str1 = {}", str1);

let str2 = str1;    // heap 메모리 str1 소유권 str2로 넘어감
let str3 = str2.clone();    // str2의 데이터를 복사하여 str3를 생성

println!("str1 = {}", str1);    // 소유권이 str2로 넘어가서 str1은 사용할 수 없음
println!("str2 = {}", str2);
println!("str3 = {}", str3);

 

 

ex) 함수 사용 예시  

  // 함수 테스트
{
    let number = 31;
    owner_function_number(number);
    println!("데이터가 복사되서 소유권 넘어가지 않음 {}", number);

    let str1 = String::from("스트링 생성");
    owner_function_string(str1);
    println!("소유권 넘어감 {}", str1); // 소유권이 넘어가서 사용 불가
}


fn owner_function_number(number: i32) {
    println!("소우권 테스트 number : {}", number)
}

fn owner_function_string(str: String) {
    println!("소유권 테스트 String : {}", str)
}

 

 

소유권을 넘겨주지 않고 임대하는 방법

  • `&`(참조)를 사용하여 소유권을 넘기지 않고 넘기거나, 받을 수 있다.
  • 기본 값은 immutable이어서 mutable시 명시해서 넘겨줘야 한다.
  • `&mut`(변경 참조)는 한 스코프 내에서 하나만 존재할 수 있다.

 

{
    let mut str1 = String::from("스트링 생성");
    owner_function_rent_string(&str1);
    println!("소유권 임대해서 넘어감 {}", str1);
    owner_function_rent_mut_string(&mut str1);
}

fn owner_function_rent_string(str: &String) {
    println!("소유권 임대 테스트 String : {}", str)
}

fn owner_function_rent_mut_string(str: &mut String) {
    str.push_str("mutable");
    println!("mutable 테스트 String : {}", str)
}