4.1 Ownership
4.1 Ownership
전통적으로는 Runtime 에 할당되는 메모리(Heap)를 관리하기 위해서는 다음과 같은 방법이 있었다.
- 프로그래머가 직접 할당 및 해제 (C, C++)
- Garbage Collector 가 계속 수행되며 메모리 해제 (Java)
전자는 프로그래머가 실수로 메모리할당을 해제하지 않는 경우가 빈번히 발생하고(리눅스 커널 코드에도 상당히 많다) 후자는 런타임에 실행되며 컴퓨팅 자원을 사용하여 프로그램이 느려질 수 있는 문제가 있다. 반면 Rust 소유권 개념을 사용해 컴파일 타임에 안전하게 메모리를 관리 할 수 있다. 오너쉽은 러스트 언어의 가장 큰 장점이자 핵심 feature 이다.
소유권이란?
소유권은 메모리를 해제할 권리이다. 소유권을 가진 것만 메모리를 해제할수 있다.
결론:
- 스택에 저장되는 값은
copy
되며, - 힙에 저장되는 값은
move
된다.move
는 소유권도 함께 이동하는것이다.
Stack and Heap
- 스택에 저장되는 것들은 함수에 선언된 변수들, 넘겨받는 매개변수들이다. 이들은 함수가 call 될때 스택에 차곡차곡 쌓인다. 이를 Activation Recode 라고 한다. 스택에 할당되는 메모리는 컴파일타임에 그 크기가 결정되어야 한다. 그래서 메모리 접근이 빠르다.
- 반면 힙은 프로그램의 실행 타임에 할당되고 해제된다. 더 느리다.
소유권은 스택이 아닌 힙메모리에만 적용된다.
힙에 데이터를 갖고 있는 변수가 스코프 밖으로 벗어나면, 해당 값은 데이터가 다른 변수에 의해 소유되도록 이동하지 않는한 drop
에 의해 제거된다.
오너쉽 규칙
- 러스트의 각각의 값은 해당값의 오너(owner)라고 불리우는 변수를 갖고 있다.
- 한번에 딱 하나의 오너만 존재할 수 있다.
- 오너가 스코프 밖으로 벗어나는 때, 값은 버려진다(dropped).
변수의 스코프
스코프는 프로그램 내에서 아이템이 유효한 범위이다. 다음의 변수 s는 하드코딩된 스트링 리터럴 값이 있다. 이 변수는 }
를 빠져나가면 더이상 유효하지 않다.
{
let s = "hello";
}
참고로 스트링 리터럴은 immutable 이다. 값을 변경 할 수 없다.
String 타입
반면 String 타입은 런타임에 값의 변경이 가능 하다.
let mut s = String::from("hello");
s.push_str(", world!"); // push_str() appends a literal to a String
println!("{}", s); // `hello, world!` will be printed.
스트링 타입과 스트링 리터럴 타입은 어떻게 메모리를 할당할까?
Memory and Allocation
러스트는 변수가 소속되어있는 스코프 밖을 벗어나는 순간 메모리를 자동으로 해제한다. 위의 예제에서 s
가 스코프 밖을 벗어날 때 drop
이라는 함수가 호출된다. 러스트는 }
괄호가 닫힐때 자동으로 drop
을 호출한다.
변수와 데이터가 상호작용하는 방법: 이동(move)
let x = 5;
let y = x;
이 경우는 x, y모두 스택에 push 되기 때문에 둘다 5 값을 갖는다.
let s1 = String::from("hello");
let s2 = s1;
반면 String 버전은 다르다. 여기서 스트링값은 s1 에서 s2로 복사가 아니라 이동(move) 되었다고 표현한다. s1은 무효화 된다. 메모리 구조는 아래와 같다. 왼쪽의 s1, s2는 포인터와 길이 등을 갖는 고정된 크기이며 스택에 저장 된다. 오른쪽은 힙에 저장될것이다.
let s1 = String::from("hello");
{
let s2 = s1;
}
println!("{}", s1);
이 코드는 컴파일 에러가 발생한다. s1은 무효화 되었기 때문이다.
변수와 데이터가 상호작용하는 방법: 클론
만약 힙 데이터까지 복사하고 싶다면 clone()
메소드를 사용할 수 있다. 하지만 힙 공간을 두배로 사용.
let s1 = String::from("hello");
{
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
}
println!("{}", s1);
s2
는 소유권을 넘겨받지 않고 복사를 했기때문에 s1
은 무효화되지 않는다. 이 코드는 동작한다.
어떤 타입을 copy
할 수 있나?
다음과 같이 스택에 저장되는 변수는 copy
된다. 이것은 소유권 개념이 적용되지 않는다.
let x = 5;
let y = x;
다음과 같은 타입들이 copy
될 수 있다.
u32
와 같은 모든 정수형 타입들true
와false
값을 갖는 부울린 타입bool
f64
와 같은 모든 부동 소수점 타입들Copy
가 가능한 타입만으로 구성된 튜플들.(i32, i32)
는Copy
가 되지만,(i32, String)
은 안됨.
소유권과 함수
함수의 인자로 변수를 전달하면 소유권또한 같이 이동한다. 아래 주석을 자세히 보자.
fn main() {
let s = String::from("hello"); // s comes into scope
takes_ownership(s); // s's value moves into the function...
// 스트링 타입 변수 s 는 이지점에서 더이상 유효하지 않다.
let x = 5; // x comes into scope
makes_copy(x); // x would move into the function,
// x 는 copy 된 것이므로 계속 x를 사용할 수 있다.
} // s 에 대한 소유권이 이전되었기 때문에 s에 대한 drop 은 여기서 일어나지 않는다. x 는 스코프를 벗어났다.
fn takes_ownership(some_string: String) { // some_string comes into scope
println!("{}", some_string);
} // Here, some_string goes out of scope and `drop` is called. The backing
// memory is freed.
fn makes_copy(some_integer: i32) { // some_integer comes into scope
println!("{}", some_integer);
} // Here, some_integer goes out of scope. Nothing special happens.
리턴값과 스코프
heap에 할당된 값을 리턴 하면 오너쉽도 리턴된다.
만일 함수에게 값만 넘기고 소유권은 넘기지 않도록 하고 싶다면? &
참조자(references) 를 사용할 수 있다. (5.2장)
fn main() {
let s1 = gives_ownership(); // gives_ownership moves its return
// value into s1
let s2 = String::from("hello"); // s2 comes into scope
let s3 = takes_and_gives_back(s2); // s2 is moved into
// takes_and_gives_back, which also
// moves its return value into s3
} // s1, s3 은 drop 이 호출된다. s2는 drop 이 호출되지 않는다.
fn gives_ownership() -> String {
let some_string = String::from("hello"); // some_string comes into scope
some_string // some_string 이 move 된다.
}
// takes_and_gives_back will take a String and return one
fn takes_and_gives_back(a_string: String) -> String {
a_string // a_string is returned and moves out to the calling function
}
Author And Source
이 문제에 관하여(4.1 Ownership), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@soopsaram/Rust-4.1-Ownership저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)