STUDY/Rust

Rust - 6. 소유권

sinawi95 2024. 2. 16. 22:50
728x90

러스트의 가장 독특한 특성이라고한다. 가비지 콜렉션을 사용하지 않기 위한 방법이라고 대충 본거같은데 한번 열심히 읽어봐야지. (사실 여러번 읽어봤는데 이해안되는 중이라 더 읽어보는중)


0. Garbage Collection

메모리 관리 방법 중 하나. 프로그래머가 동적으로 할당한 메모리 영역 중 더 이상 쓰이지 않는 영역을 자동으로 찾아내어 해제하는 기능이다. 반복적으로 찾기 때문에 오버헤드가 있다. GC는 python, java, javascript 등에서 쓰인다. (c, c++은 동적으로 메모리를 할당하고 사용하지 않는 경우 직접(수동으로) 해제해야한다.)

종류로는 Tracing GC, Reference Counting based GC 가 있다.

1. 소유권

GC를 사용하지 않고 메모리를 관리하는 방식. 동적으로 관리하지 않고 규칙을 통해 컴파일 단계에서 관리하도록 도움.

소유권 규칙

  1. 러스트에서 각각의 값은 소유자가 있다.(owner)
  2. 한 값의 소유자는 동시에 여럿 존재할 수 없다.
  3. 소유자가 스코프 밖으로 벗어날 때, 값은 버려진다.(drop)

(+) Resource Acquisition Is Initialization (RAII): : 아이템의 수명이 끝나는 시점에 리소스를 해제하는 패턴. C++에서 사용 

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;

    println!("{}, world!", s1);
}
  • 여기서 에러가 생긴다는 걸 알고 이유를 정확하게 안다면 소유권 마스터라고 볼 수 있다.
  • 내가 이해한 바는 아래와 같다.(사실 써있는거 내 방식으로 이해한거다)
    • String으로 선언하면 데이터는 힙 영역에 저장한다. 이후에 추가가 가능. (let s1 = "hello"; 와 다름. 이경우엔 에러가 발생하지 않음)
    • let s2=s1;에서 s2가 가리키는 게 s1이 가리키는 데이터와 동일해진다. 이때 소유권이 이전된다. 소유권이 이전되는 이유는 main 함수가 끝났을때 s1과 s2이 가리키는 힙 영역 메모리를 해제를 해야하는데 s1 한번 s2 한번 해제를 하게되면 두번째 해제할때 이미 힙 영역 데이터가 지워지므로 에러가 발생하게 된다. 이를 방지하기 위해 let s2 = s1;에서 변수 s1을 무효화해버리고 main 이 끝날때 s2를 drop한다.

clone: 힙 영역에 있는 데이터를 복사하기 위한 방법

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();

    println!("s1 = {}, s2 = {}", s1, s2);
}

 

2. 참조와 대여

소유권을 넘기지 않는 방법이다. 소유권 대신 개체의 참조자(reference)를 넘겨서 소유권 이전이 생기지 않도록 한다.

  • 참조자를 사용하는 경우 소유권이 없으므로 값을 수정할수 없다. 하지만 가변 참조자(mutable reference)를 만들면 값을 수정할 수 있다.
  • race condition을 피하기 위해 가변 참조자는 하나만 생성할 수 있다. 
    • 새로운 스코프(블록)을 만들어서 해결할 순 있다. 
    • 불변, 가변 섞어쓸때도 불변 참조자가 하나있으면 가변 참조자를 만들수 없다.

댕글링 참조

댕글링 포인터 (dangling pointer) 란, 어떤 메모리를 가리키는 포인터가 남아있는 상황에서 일부 메모리를 해제해 버림으로써, 다른 개체가 할당받았을지도 모르는 메모리를 참조하게 된 포인터를 말합니다

특정 함수에서 힙 데이터를 설정하고 반환 값으로 힙 데이터를 넘겨야할때는 참조로 넘기지 말고 값을 직접 넘겨서 소유권을 넘거야한다.

3. 슬라이스

컬렉션 일부를 참조하는 것. 소유권을 갖지 않음

fn main() {
    let s = String::from("hello world");

    let hello = &s[0..5];
    let world = &s[6..11];
}

 

슬라이스 챕터는 뭔가 바로 이해되진않는다. 그냥 "파이썬 배열 슬라이스처럼 잘라서 쓸수 있다." 정도로 이해하면 될려나


https://doc.rust-kr.org/ch04-00-understanding-ownership.html

https://doc.rust-kr.org/ch04-01-what-is-ownership.html

https://doc.rust-kr.org/ch04-02-references-and-borrowing.html

https://doc.rust-kr.org/ch04-03-slices.html