ガベージコレクターの代わりにRustには何がありますか?


95

Rustにはガベージコレクターがないことを理解しており、バインディングがスコープ外になったときにメモリがどのように解放されるのか疑問に思っています。

したがって、この例では、Rustがスコープ外になると、「a」に割り当てられたメモリを再利用することを理解しています。

{
    let a = 4
}

私がこれに関して抱えている問題は、第一にこれがどのように起こるかであり、第二にこれは一種のガベージコレクションではありませんか?「典型的な」ガベージコレクションとどう違うのですか?


12
「決定論的オブジェクトの存続期間」。C ++に似ています。
user2864740 2015

@ user2864740そのガイドはかなり時代遅れです。最新の代替品はおそらくdoc.rust-lang.org/book/references-and-borrowing.htmlでしょう。
Veedrac 2015

回答:


74

ガベージコレクションは通常、ヒープがいっぱいに近いか、あるしきい値を超えている場合など、定期的またはオンデマンドで使用されます。次に、アルゴリズムに応じて、未使用の変数を探し、それらのメモリを解放します

Rustは、変数がスコープから外れるか、コンパイル時にその存続期間が終了するかを認識し、対応するLLVM /アセンブリ命令を挿入してメモリを解放します。

Rustでは、アトミック参照カウントなど、ある種のガベージコレクションも可能です。


変数を導入するときにメモリを割り当て、メモリが不要になったときにメモリを解放することによって?それで何を言いたいのかよくわかりません。たぶん、GCが何であるかについて私たちは異なる意見を持っています。
Ayonix 2015

1
彼の質問は、Rustのアプローチが典型的なGCとどのように異なるかということです。そこで、GCとは何か、そしてRustがGCなしでそれを行う方法を説明しました。
Ayonix 2015

1
doc.rust-lang.org/book/the-stack-and-the-heap.htmlはそれをかなりよく説明しています。はい、多くのものがスタックにありますが、言うまでもなく十分な指標ではありません(ボックスを参照)。質問は一般的に尋ねられていたので、簡単にするためにそれを
省略しまし

1
@Amomum実際、Rustにはnew()Cのような油そそがれた関数はなく、単なる静的関数であり、特にlet x = MyStruct::new()スタック上にオブジェクトを作成するようなものです。ヒープ割り当ての実際の指標はBox::new()(またはBoxに依存する構造のいずれか)です。
マリオカルネイロ2016

1
Rustと同様の方法でメモリ管理を処理する他の言語は何ですか?
still_dreaming_1 2017年

43

プログラム内のリソース(メモリを含む)を管理する基本的な考え方は、戦略に関係なく、到達不能な「オブジェクト」に関連付けられているリソースを再利用できるということです。メモリ以外に、これらのリソースには、ミューテックスロック、ファイルハンドル、ソケット、データベース接続などがあります。

ガベージコレクターを備えた言語は、定期的にメモリをスキャンして(何らかの方法で)未使用のオブジェクトを見つけ、それらに関連付けられているリソースを解放し、最後にそれらのオブジェクトによって使用されているメモリを解放します。

RustにはGCがありませんが、どのように管理しますか?

Rustには所有権があります。アフィン型システムを使用して、どの変数がまだオブジェクトを保持しているかを追跡し、そのような変数がスコープ外になると、そのデストラクタを呼び出します。アフィン型システムの効果を簡単に確認できます。

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自身に関連付けられているメモリバッファを解放する

したがって、所有権の追跡のおかげで、すべてのプログラムオブジェクトの存続期間は、1つ(または複数)の関数変数に厳密に関連付けられ、最終的にはスコープ外になります(それらが属するブロックが終了すると)。

注:これは少し楽観的です。参照カウント(RcまたはArc)を使用すると、参照のサイクルを形成してメモリリークを引き起こす可能性があります。その場合、サイクルに関連付けられたリソースが解放されない可能性があります。


2
「ガベージコレクターを使用する言語は、定期的にメモリをスキャンします(何らかの方法で)」。多くの人がそうしますが、それは一般的に真実ではありません。リアルタイムのガベージコレクタは、定期的ではなく段階的にスキャンします。Mathematicaのような参照カウント言語はまったくスキャンしません。
JD 2016年

@JonHarrop:参照カウントは、サイクルのリークを回避するために補足する必要があるため、完全なガベージコレクションメカニズムとしてはカウントしません。インクリメンタル/周期的な違いについては、英語が苦手かもしれませんが、周期的にインクリメンタルなケースをカバーしていないのがわかりません...「(何らかの方法で)」ビットは、その多くのバリエーションを適切に伝えていると思いますアプローチが存在します。いずれにせよ、ガベージコレクションを簡潔に説明するためのより良い方法がある場合は、遠慮なく提案してください。しかし、私は本格的な説明で自分自身を立ち上げるつもりはありません。私はその資格がありません。
Matthieu M. 2016

1
「参照カウントは、サイクルのリークを回避するために補足する必要があるため、完全なガベージコレクションメカニズムとしてはカウントしません」。RCは従来GCの一形態と見なされていました。たとえばMathematicaやErlangでは、設計上サイクルを作成できないため、RCがリークすることはありません。高レベルの視点については、「ガベージコレクションの統一理論」cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
JD

@JonHarrop:本当です。サイクルが不可能な場合、RCはリークできません。
Matthieu M.

2
「定期的にインクリメンタルのケースがカバーされていないことがわかりません」。たとえば、Stop the worldアルゴリズムは周期的と見なされますが、トリコロールマーキングはインクリメンタルと見なされます。この文脈では、それらは反対です。
JD 2016年

6

手動でメモリを管理する必要がある言語では、スタックとヒープの区別が重要になります。関数を呼び出すたびに、その関数のスコープ内に含まれるすべての変数に対して十分なスペースがスタックに割り当てられます。関数が戻ると、その関数に関連付けられているスタックフレームがスタックから「ポップ」され、メモリは将来の使用のために解放されます。

実用的な観点から、この不注意なメモリクリーニングは、関数のスコープの最後にクリアされる自動メモリストレージの手段として使用されます。

ここで利用可能な詳細情報があります:https//doc.rust-lang.org/book/the-stack-and-the-heap.html


3
スタックの使用は便利ですが、すべての値が「ヒープ上に作成された」場合でも、確定的なオブジェクトの有効期間を処理できます。したがって、これは実装の詳細です。必ずしも言語戦略ではありません。
user2864740 2015

2
あなたはその言葉を使い続けます。私はそれがあなたがそれが意味すると思うことを意味するとは思わない。
スイス

私が表現したいことを意味します; 非決定論的寿命の反対です。より良いフレーズを提案します。
user2864740 2015

答えてくれてありがとう、最初に提出されたという理由だけで最初のものにポイントを与えました。情報は同様に有用で有効です。
rix

@ user2864740確定的オブジェクトの有効期間とは、デストラクタが呼び出された後、オブジェクトのメモリがいつクリアされるかを正確に伝えることができることを指します。そもそも、そのデストラクタがどのように呼び出されるかとは関係ありません。質問に直接的な意味はありませんが、同じ用語を繰り返し取り上げます。
スイス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.