시뻘건 개발 도전기

러스트 11 - References와 Borrowing 본문

프로그래밍/RUST

러스트 11 - References와 Borrowing

시뻘건볼때기 2019. 3. 2. 19:32
반응형



다음 코드를 컴파일해보자.

fn main() {

    let str = String::from("string");

    let length = get_length(&str);

    println!("================= get_length() finish! =================");


    println!("str의 값 : [{}]", str);

    println!("str의 길이 : [{}]", length);

}


fn get_length(func_str: &String) -> usize {

    println!("================= get_length() start! =================");

    println!("func_str의 값 : [{}]", func_str);

    func_str.len()

}




"&"(Ampersand : 앰퍼샌드)라는 녀석이 새로 등장했다.

이 녀석은 참조자라 불리고 소유권을 가지지 않고 어떤 값을 참조하도록 해준다.

그림을 통해 보면 이해가 쉬울 것 같다..




※ 참조자 Ampersand의 반대는 역참조 "*"(Asterisk : 아스트리스크)를 사용한다.


Ampersand를 사용하여 소유권을 갖지 않기 때문에 scope 밖으로 벗어나도 메모리가 반환되지 않는다.

어차피 함수가 소유권이 없으니.. 반환할 필요도 없지요.

함수의 파라미터로 참조자를 받는 것을 "borrowing"이라고 부릅니다.

참고로 참조자도 기본적으로 불변의 성질을 가지고 있습니다.

하지만 이 참조자 역시 가변의 성질을 넣을 수 있습니다.


fn main() {

    let mut str = String::from("string");

    println!("str 값 : [{}]", str);


    set_str(&mut str);

}


fn set_str(func_str: &mut String) {

    func_str.push_str(" / new string");


    println!("func_str 값 : [{}]", func_str);

}



참조자에 가변성을 추가하는 것은 rust로부터 큰 제한이 있습니다.

"해당 scope 내에서는 가변 참조자는 단 하나만 존재할 수 있어" 라는 것.

이 점. 유의하자.


도대체 왜?

이 제한의 이득(Benefit)이 따로 있다. 바로 compile timeData Race를 방지 할 수 있다는 것!

Data Race의 발생 조건은 다음과 같다.

    • 두 개 이상의 포인터가 동시에 같은 데이터에 접근한다.
    • 최소 하나 이상의 포인터가 데이터를 "쓰기"로 사용한다.
    • 데이터에 대한 접근을 동기화(Synchronize)하는 데 사용되는 메커니즘이 없다.


Data Race는 정의되지 않은 동작을 발생 시키고 runtime에 추적할 때 fix하기 어렵다.

rust는 이런 좋지 않은 상황을 방지하기 위해 가변 참조자에 대한 제한을 걸어 둔 것이다!





  • Dangling Reference
포인터를 가진 언어에서 잘못 했다가는 dangling pointer를 만들기 쉽다.
dangling pointer란, 메모리에 포인터를 보존하면서 일부 메모리를 반환하여 다른 개체에게 부여되었을 수 있는 메모리 위치를 참조하는 포인터를 말한다.

rust에서는 컴파일러가 참조자들이 dangling pointer가 되지 않도록 해준다.

만약 일부 데이터에 대한 참조가 있다면 컴파일러는 데이터 참조가 적용되기 전에 데이터가 scope를 벗어나지 않도록 해준다.


dangling pointer를 한 번 만들어보자.

fn main() {

    let no = get_dangle_pointer();

}


fn get_dangle_pointer() -> &String {

    let str = String::from("string");

    &str

}



한 번 해결책을 찾길 바란다.

만약, 참조를 이해를 했다면, 바로 해결 방법이 떠오를 것이다.

반응형

'프로그래밍 > RUST' 카테고리의 다른 글

러스트 13 - 구조체 #1  (0) 2019.03.10
러스트 12 - 슬라이스 타입  (0) 2019.03.03
러스트 10 - Ownership : 소유권 #2  (0) 2019.03.02
러스트 9 - Ownership : 소유권 #1  (0) 2019.02.24
러스트 8 - 주석  (0) 2019.02.23
Comments