러스트(Rust) 언어의 소유권(Ownership) 개념 소개

병신·2023년 3월 24일
0

Rust Book Experiment로 러스트의 개념을 짚어보는 도중 특이한 방식의 메모리 관리를 사용하고 있는 사실을 찾았다. 메모의 필요성을 느껴 이곳에 정리해둔다.

개요

C나 C++같은 경우는 malloc과 free와 같은 명령어로 개발자가 동적으로 메모리를 할당하거나 해제합니다. java나 javascript같은 경우 가비지컬렉션이 메모리에서 상주하면서 필요없는 메모리를 힙에서 정리합니다.

그에 반해 러스트는 가비지 컬렉션도 돌아가지 않고 개발자가 수동으로 메모리를 관리하게끔 허용하지도 않습니다. 대신 소유권이라는 방식으로 자체적으로 메모리를 관리합니다. 이 개념은 아래의 세가지 규칙 위에서 동작합니다.

  1. 힙 위의 모든 데이터는 하나의 변수만 소유(Owner)할 수 있다.
  2. 스코프를 벗어난 값은 힙 데이터에 할당이 해제된다.
  3. 주인이 없는 값은 drop된다.

소유권은 힙 메모리를 사용하는 데이터에게 적용되는 개념이기 때문에 먼저 힙과 스택의 차이점을 알 필요가 있습니다.

힙과 스택

스택

스택은 아까 설명한 소유권의 개념이 동작하지 않습니다. 스택은 소유권이 없기 때문에 다음과 같이 특정 변수에 변수를 대입하여도 소유권 이동이 발생하지 않고, 일반적인 프로그래밍 언어의 대입과 같이 값이 복사됩니다.

let a = 5;
let mut b = a;
b += 1;

다음 로직을 수행한 결과 스택에는 a = 5, b = 6의 두가지 값이 메모리에 남게됩니다. 스택메모리에 할당되는 변수들은 일반적인 정수, 실수 자료형과 char와 같은 경우입니다. 그런값들로 이루어진 튜플의 경우도 마찬가지로 스택메모리에 할당됩니다.

    let fruit = String::from("banana");
    let banana = fruit; 
    println!("{}",fruit);  // 에러

위 로직은 오류가 발생합니다. 처음 개요에서 설명한 규칙이 동작했기 때문입니다. 힙 위의 데이터는 하나의 변수만 소유 할 수 있고, 문자열은 힙에 상주하는 데이터입니다. 그리고 banana변수에 fruit 변수를 대입하는 과정에서 fruit 변수의 소유권은 banana에게 넘어갔습니다. 결과적으로 fruit은 현재 아무런 내용이 없는 껍데기뿐인 변수가 되었습니다.

기타 케이스

이러한 현상은 함수에서도 나타납니다.

fn main(){
    let fruit = String::from("banana");
    print_fruit(fruit);
    println!("{}",fruit); // 에러
}

fn print_fruit(fruit: String){
    println!("{}",fruit); 
}

위 소스는 오류가 발생합니다. 에러가 나기까지 메모리의 할당 과정은 다음과 같습니다.

  • "banana"라는 데이터가 힙메모리에 할당됨
  • fruit의 소유권이 print_fruit의 파라미터로 옮겨감
  • 함수가 종료되면서 파라미터가 스코프에서 벗어나게 되고 자동으로 메모리 할당 해제

할당이 해제되면서 과일값은 어디에서도 접근 할 수 없게 되었습니다. 함수에 넘겨준 뒤에도 값을 사용하고 싶은 경우에는 일반적으로 변수의 복사와 소유권의 임대, 소유권의 반환과 같은 방법으로 변수의 소유권을 유지합니다.

0개의 댓글