https://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)
}