Rust는 가비지 수집기 대신 무엇을 가지고 있습니까?


95

Rust에는 가비지 컬렉터가 없으며 바인딩이 범위를 벗어날 때 메모리가 어떻게 해제되는지 궁금합니다.

그래서이 예제에서 저는 Rust가 범위를 벗어날 때 'a'에 할당 된 메모리를 회수한다는 것을 이해합니다.

{
    let a = 4
}

내가 가진 문제는 첫째로 이것이 어떻게 발생하는지, 둘째로 이것은 일종의 가비지 수집이 아닙니까? '일반적인'가비지 수집과 어떻게 다릅니 까?


12
"결정적 개체 수명". C ++와 유사합니다.
user2864740 '152015-09-20

@ user2864740 그 가이드는 오래되었습니다. 현대적인 대체물은 아마도 doc.rust-lang.org/book/references-and-borrowing.html 일 것입니다 .
Veedrac

답변:


74

가비지 콜렉션은 일반적으로 힙이 가득 차거나 일부 임계 값을 초과하는 경우와 같이 주기적으로 또는 요청시 사용됩니다. 그런 다음 사용되지 않는 변수를 찾아 알고리즘 에 따라 메모리를 해제 합니다 .

Rust는 변수가 범위를 벗어나거나 그 수명이 컴파일 타임에 종료되는시기를 알고 있으므로 해당 LLVM / 어셈블리 명령어를 삽입하여 메모리를 해제합니다.

Rust는 또한 원자 참조 계산 과 같은 일종의 가비지 수집을 허용 합니다.


변수를 도입 할 때 메모리를 할당하고 더 이상 메모리가 필요하지 않을 때 메모리를 해제함으로써? 나는 당신이 그것에 대해 무엇을 말하고 싶은지 정말로 모릅니다. 아마도 우리는 GC가 무엇인지에 대해 다른 의견을 가지고있을 것입니다.
Ayonix

1
그의 질문은 Rust의 접근 방식이 일반적인 GC와 어떻게 다른지입니다. 그래서 GC가 무엇인지, Rust가 GC없이 어떻게 하는지를 설명했습니다.
Ayonix

1
doc.rust-lang.org/book/the-stack-and-the-heap.html은 잘 설명합니다. 예, 많은 것들이 스택에 있지만 충분한 지표는 말할 것도 없습니다 (박스 참조). 문제는 일반적으로하지만 요청 이후 나는 간단하게하기 위해 그 왼쪽으로
Ayonix

1
@Amomum 실제로 Rust는 new()C와 같은 기름 부음 된 함수를 가지고 있지 않습니다 . 그것들은 단지 정적 인 함수이며, 특히 let x = MyStruct::new()스택에 객체를 생성하는 것과 같은 것 입니다. 힙 할당 의 실제 지표는 Box::new()(또는 Box에 의존하는 구조)입니다.
마리오 Carneiro

1
Rust와 비슷한 방식으로 메모리 관리를 처리하는 다른 언어는 무엇입니까?
still_dreaming_1

43

전략이 무엇이든 프로그램에서 리소스 (메모리 포함)를 관리하는 기본 아이디어는 도달 할 수없는 "개체"에 연결된 리소스를 회수 할 수 있다는 것입니다. 메모리 외에도 이러한 리소스는 뮤텍스 잠금, 파일 핸들, 소켓, 데이터베이스 연결 등이 될 수 있습니다.

가비지 수집기가있는 언어는 주기적으로 메모리를 스캔하여 사용하지 않는 개체를 찾고, 연결된 리소스를 해제하고, 마지막으로 해당 개체에서 사용하는 메모리를 해제합니다.

Rust에는 GC가 없습니다. 어떻게 관리합니까?

Rust는 소유권이 있습니다. affine 유형 시스템을 사용하여 어떤 변수가 여전히 객체를 잡고 있는지 추적하고 이러한 변수가 범위를 벗어나면 소멸자를 호출합니다. 효과가있는 아핀 유형 시스템을 매우 쉽게 볼 수 있습니다.

fn main() {
    let s: String = "Hello, World!".into();
    let t = s;
    println!("{}", s);
}

수율 :

<anon>:4:24: 4:25 error: use of moved value: `s` [E0382]
<anon>:4         println!("{}", s);

<anon>:3:13: 3:14 note: `s` moved here because it has type `collections::string::String`, which is moved by default
<anon>:3         let t = s;
                     ^

이는 어느 시점에서든 언어 수준에서 소유권이 추적된다는 것을 완벽하게 보여줍니다.

이 소유권은 재귀 적으로 작동합니다. 만약 당신이 Vec<String>(즉, 문자열의 동적 배열) 을 가지고 있다면 , 각각 StringVec변수 나 다른 객체 등이 소유하고있는에 의해 소유됩니다. 따라서 변수가 범위를 벗어날 때, 간접적으로도 보유한 모든 리소스를 반복적으로 해제합니다. 이 경우 Vec<String>다음을 의미합니다.

  1. 각각에 연결된 메모리 버퍼 해제 String
  2. Vec자신 과 관련된 메모리 버퍼 해제

따라서 소유권 추적 덕분에 모든 프로그램 개체의 수명은 하나 (또는 ​​여러) 함수 변수에 엄격하게 연결되어 궁극적으로 범위를 벗어납니다 (그들이 속한 블록이 끝날 때).

참고 : 이것은 다소 낙관적입니다. 참조 카운트 ( Rc또는 Arc)를 사용하면 참조 주기를 형성하여 메모리 누수를 일으킬 수 있으며,이 경우주기에 연결된 리소스가 해제되지 않을 수 있습니다.


2
"가비지 콜렉터가있는 언어는 주기적으로 메모리를 스캔합니다 (단방향 또는 다른 방법)". 많은 사람들이하지만 그것은 일반적으로 사실이 아닙니다. 실시간 가비지 수집기는 주기적으로가 아니라 점진적으로 검색합니다. Mathematica와 같은 참조 계산 언어는 전혀 스캔하지 않습니다.
JD

@JonHarrop : 참조 계산을 완전한 가비지 수집 메커니즘으로 간주하지 않습니다. 누출주기를 방지하기 위해 보완해야하기 때문입니다. 점진적 / 주기적 차이에 관해서는 저의 영어 구사력이 좋지 않을 수 있지만 주기적이 점진적 사례를 얼마나 다루지 않는지 알 수 없습니다. "(one way or another)"비트가 여러 가지를 적절히 전달한다고 생각합니다. 접근 방식이 존재합니다. 어쨌든 가비지 컬렉션을 간결하게 설명하는 더 좋은 방법이 있다면 멀리 제안하십시오. 그러나 나는 본격적인 설명으로 나 자신을 시작할 의도가 없습니다. 나는 그것에 대한 자격이 없습니다.
Matthieu M.

1
"누수주기를 피하기 위해 보완되어야하므로 참조 계수를 완전한 가비지 수집 메커니즘으로 간주하지 않습니다." RC는 일반적으로 GC의 한 형태로 간주됩니다. 예를 들어 Mathematica와 Erlang에서 사이클은 설계에 의해 생성 될 수 없으므로 RC가 누출되지 않습니다. 높은 수준의 관점은 "가비지 수집의 통합 이론"을 참조하십시오. cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
JD

@JonHarrop : True, 사이클이 가능하지 않으면 RC가 누출 될 수 없습니다.
Matthieu M.

2
"나는 증분 사례를 어떻게 주기적으로 다루지 않는지 알지 못한다". 예를 들어 세계 중지 알고리즘은 주기적으로 간주되는 반면 삼색 표시는 증분으로 간주됩니다. 이 맥락에서 그들은 반대입니다.
JD

6

메모리를 수동으로 관리해야하는 언어에서는 스택과 힙 간의 차이가 중요해집니다. 함수를 호출 할 때마다 해당 함수 범위 내에 포함 된 모든 변수에 대해 스택에 충분한 공간이 할당됩니다. 함수가 반환되면 해당 함수와 관련된 스택 프레임이 스택에서 "팝 (pop)"되고 메모리는 향후 사용을 위해 해제됩니다.

실제적인 관점에서이 부주의 한 메모리 정리는 함수 범위의 끝에서 삭제되는 자동 메모리 저장 수단으로 사용됩니다.

여기에 더 많은 정보가 있습니다 : https://doc.rust-lang.org/book/the-stack-and-the-heap.html


3
스택을 사용하는 것이 편리하지만 모든 값이 '힙에서 생성'된 경우 결정적 개체 수명을 계속 처리 할 수 ​​있습니다. 따라서 이것은 구현 세부 사항입니다. 반드시 언어 전략은 아닙니다.
user2864740 '152015-09-20

2
당신은 그 단어를 계속 사용합니다. 나는 그것이 당신이 의미한다고 생각하는 것을 의미하지 않는다고 생각합니다.
스위스

내가 표현하고 싶은 것을 의미 한다 . 비 결정적 수명의 반대입니다. 더 나은 문구를 제안하십시오.
user2864740

답변 해 주셔서 감사합니다. 첫 번째 항목이 먼저 제출 되었기 때문에 첫 번째 항목에 포인트를 부여했습니다. 정보는 유용하고 유효합니다.
rix

@ user2864740 결정 론적 개체 수명은 소멸자가 호출 된 후 개체의 메모리가 지워지는시기를 정확히 알 수 있음을 의미합니다. 소멸자가 처음에 호출되는 방식과는 관련이 없습니다. 질문에 직접적인 의미가 없더라도 같은 용어를 계속 반복해서 언급합니다.
Swiss
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.