まあ、Cにはmalloc / free、C ++にはメモリ管理にnew / using-a-de-structorのようなものがあることは知っていますが、ユーザーがこれらの言語に「新しい更新」がないのはなぜだろうメモリを手動で管理するオプションがありますか、またはシステムが自動的にメモリを管理するオプションがあります(ガベージコレクション)。
やや新しい質問ですが、CSに約1年しかいません。
まあ、Cにはmalloc / free、C ++にはメモリ管理にnew / using-a-de-structorのようなものがあることは知っていますが、ユーザーがこれらの言語に「新しい更新」がないのはなぜだろうメモリを手動で管理するオプションがありますか、またはシステムが自動的にメモリを管理するオプションがあります(ガベージコレクション)。
やや新しい質問ですが、CSに約1年しかいません。
回答:
ガベージコレクションには、割り当ての追跡や参照カウントのためのデータ構造が必要です。これらにより、メモリ、パフォーマンス、および言語の複雑さがオーバーヘッドになります。C ++は「金属に近い」ように設計されています。つまり、利便性機能とのトレードオフよりもパフォーマンスの面を重視しています。他の言語では、トレードオフが異なります。これは、言語を選択する際の考慮事項の1つです。
とは言っても、かなり軽量でパフォーマンスの高いC ++の参照カウントには多くのスキームがありますが、それらは言語自体の一部ではなく、商用およびオープンソースの両方のライブラリにあります。オブジェクトの有効期間を管理するための参照カウントは、ガベージコレクションと同じではありませんが、同じ種類の問題の多くに対処し、C ++の基本的なアプローチにより適しています。
厳密に言えば、C言語にはメモリ管理はまったくありません。malloc()およびfree()は言語のキーワードではなく、ライブラリから呼び出される関数にすぎません。malloc()とfree()はC標準ライブラリの一部であり、Cの標準に準拠した実装によって提供されるため、この区別は今では教訓的かもしれませんが、これは過去には必ずしも当てはまりませんでした。
メモリ管理の標準がない言語が必要なのはなぜですか?これは、「ポータブルアセンブリ」としてCの起源に戻ります。特殊なメモリ管理技術の恩恵を受けたり、必要とするハードウェアやアルゴリズムの多くのケースがあります。私の知る限り、Javaのネイティブメモリ管理を完全に無効にして独自のメモリ管理に置き換える方法はありません。これは、一部の高性能/最小リソースの状況では受け入れられません。Cは、プログラムが使用するインフラストラクチャを正確に選択するためのほぼ完全な柔軟性を提供します。支払われる代償は、C言語は、バグのない正しいコードを書くのにほとんど役に立たないということです。
malloc()
もしませんfree()
。(例はPICのMLAPコンパイラです)
本当の答えは、安全で効率的なガベージコレクションメカニズムを作成する唯一の方法は、不透明な参照を言語レベルでサポートすることです。(または、逆に、直接メモリ操作に対する言語レベルのサポートの欠如。)
JavaとC#には、操作できない特別な参照型があるため、これを行うことができます。これにより、ランタイムは、割り当てられたオブジェクトをメモリ内で移動するなどのことを自由に行うことができます。これは、高性能GCの実装に不可欠です。
記録に関しては、現代のGC実装では参照カウントを使用していないため、完全に赤いニシンです。最新のGCは世代別コレクションを使用します。この場合、新しい割り当ては、C ++のような言語のスタック割り当てと本質的に同じ方法で処理されます。のオブジェクトの割り当てが一度に解除されます。
このアプローチには長所と短所があります:利点は、GCをサポートする言語でのヒープ割り当てがGCをサポートしない言語でのスタック割り当てと同じくらい速いことであり、欠点はどちらかを破棄する前にクリーンアップを実行する必要があることです別のメカニズム(C#のusing
キーワードなど)が必要です。そうでない場合、クリーンアップコードは非決定的に実行されます。
高性能GCの鍵の1つは、特別なクラスの参照に対する言語サポートが必要であることに注意してください。Cはこの言語をサポートしておらず、今後もサポートしません。C ++には演算子のオーバーロードがあるため、GCのポインター型をエミュレートできますが、慎重に行う必要があります。実際、MicrosoftがCLR(.NETランタイム)の下で実行するC ++の方言を発明したときFoo^
、「C ++スタイルの参照」と区別するために、「C#スタイルの参照」の新しい構文を考案する必要がありました。 (例Foo&
)。
C ++には、C ++プログラマーが定期的に使用しているのは、実際には単なる参照カウントメカニズムであるスマートポインターです。参照カウントは「真の」GCとは見なしませんが、手動メモリ管理や真のGCよりもパフォーマンスが低下するという犠牲を払って、決定的な破壊という利点があるにもかかわらず、多くの同じ利点を提供します。
結局のところ、答えは本当に言語設計機能に帰着します。Cは1つの選択を行い、C ++はほとんどの目的に十分な代替手段を提供しながらCとの下位互換性を可能にする選択を行い、JavaとC#はCとの互換性はないがほとんどの目的。残念ながら、特効薬はありませんが、さまざまな選択肢に精通していれば、現在作成しようとしているプログラムに適した選択肢を選択できます。
std::unique_ptr
は「不透明な参照に対する言語レベルのサポート」だと言っていますか?(それは私が意味のサポートのようなものではなかった、と私はまた、ダイレクトメモリ操作のサポートもC ++から削除されない限りそれは十分ではないと思う。)私は私の答えでスマートポインタを言及しない、と私は考えるでしょうstd:unique_ptr
スマートポインタを、実際に参照カウントを行うため、参照の数が0または1である(およびstd::move
参照カウント更新メカニズムである)特殊なケースのみをサポートします。
std::unique_ptr
参照カウントを持たず、参照とstd::move
はまったく関係ありません(つまり、パフォーマンスヒットは「ありません」)。ただし、std::shared_ptr
暗黙的に参照カウントが更新されているように、std::move
:)
malloc
とより速くなることはありませんfree
。そのため、はい、GCは大幅に高速化できます。(「できる」と言ったことに注意してください。もちろん、各プログラムの正確なパフォーマンスは多くの要因の影響を受けます。)
なぜなら、C ++のパワーを使用する場合、必要がないからです。
ハーブサッター:「長年、削除を書いたことはありません。」
最新のC ++コードの記述: 21 : 10でのC ++の進化を参照してください。
多くの経験豊富なC ++プログラマを驚かせるかもしれません。
「すべて」のガベージコレクターは、メモリ内に参照されていないオブジェクトがあるかどうか、およびそれらが削除されているかどうかを定期的に確認するプロセスです。(はい、これは非常に単純化しすぎです)。これは言語のプロパティではなく、フレームワークのプロパティです。
- CおよびC ++のために書かれたガベージコレクタがあります。この1例は。
言語に「追加」されていない理由の1つは、メモリを管理するために独自のコードを使用するため、決して使用しない既存のコードの膨大な量が原因である可能性があります。別の理由として、CおよびC ++で記述されたタイプのアプリケーションは、ガベージコレクションプロセスに関連するオーバーヘッドを必要としない可能性があります。
malloc
とfree
、正しいプログラムが壊れます。
free
それが完了するまで電話しません。しかし、私が明示的に呼び出すまでメモリを解放しない提案されたガベージコレクターfree
は、ガベージコレクターではありません。
正確な引用符はありませんが、BjarneとHerb Sutterの両方が次のように述べています。
C ++にはガベージコレクターは必要ありません。ガベージコレクターはガベージがないためです。
最新のC ++では、スマートポインターを使用するため、ゴミがありません。
オプションのガベージコレクタを含めるためにこれらの言語が更新されていない理由を尋ねます。
オプションのガベージコレクションの問題は、異なるモデルを使用するコードを混合できないことです。つまり、ガベージコレクターを使用していることを前提とするコードを記述した場合、ガベージコレクションがオフになっているプログラムでは使用できません。あなたがそうするなら、それはどこにでも漏れます。
ガベージコレクションを使用した言語でデバイスハンドラを記述することを想像できますか?GCの実行中に何ビットがラインに届くでしょうか?
またはオペレーティングシステム?カーネルを起動する前に、ガベージコレクションの実行を開始するにはどうすればよいですか?
Cは、ハードウェアタスクに近い低レベル用に設計されています。問題?それは非常に素晴らしい言語であり、多くの高レベルのタスクにも適しています。言語皇帝はこれらの使用法を認識していますが、デバイスドライバー、組み込みコード、およびオペレーティングシステムの要件を優先度としてサポートする必要があります。
この質問に対する簡潔で退屈な答えは、ガベージコレクターを作成する人々のために、ガベージコレクションされていない言語が必要であるということです。それは同時に、メモリレイアウトを非常に正確に制御することができます言語持っている概念的に簡単ではありませんし、上で実行されているGCを持っています。
もう1つの質問は、CおよびC ++にガベージコレクターがない理由です。まあ、私はC ++がそれらのいくつかを持っていることを知っていますが、そもそもGCで処理されるように設計されていない言語と、この時代は、GCを見逃すようなものではありません。
また、GCを古いGC以外の言語に追加する代わりに、GCをサポートしながらほとんど同じ構文を持つ新しい言語を実際に作成する方が簡単です。JavaとC#はこの良い例です。
など、さまざまな問題があります...
delete
またはfree
明示的に行う必要性と同じです。GCアプローチにはまだ利点があります-ぶら下がり参照はありません-静的解析はいくつかのケースをキャッチできますが、すべてのケースに完璧なソリューションはありません。基本的に、部分的には言語の年齢についてですが、とにかく非GC言語の場所は常にあります-たとえそれがちょっとニチャイの場所であっても。そして真剣に、C ++では、GCの欠如は大したことではありません-あなたのメモリは異なって管理されますが、管理されていません。
Microsoftが管理するC ++には、同じアプリケーションでGCと非GCを混在させる機能が少なくともいくつかあり、それぞれの利点を組み合わせて使用できますが、実際にこれがどの程度うまく機能するかを経験することはできません。
私の関連する回答への担当者リンク...
ガベージコレクションは、DMA対応ハードウェアのドライバーの開発に使用されるシステム言語と基本的に互換性がありません。
オブジェクトへの唯一のポインタが周辺機器のハードウェアレジスタに格納されることは完全に可能です。ガベージコレクターはこれを知らないため、オブジェクトが到達不能であると判断し、収集します。
この引数は、GCを圧縮するためにdoubleを保持します。ハードウェアペリフェラルで使用されるオブジェクトへのメモリ内参照を慎重に維持したとしても、GCがオブジェクトを再配置したとき、ペリフェラル構成レジスタに含まれるポインタを更新する方法がわかりません。
そのため、固定DMAバッファーとGC管理オブジェクトの混合が必要になります。つまり、両方の欠点がすべてあります。
C ++とCにはガベージコレクターがあります。Cでこれがどのように機能するかはわかりませんが、C ++ではRTTIを利用してオブジェクトグラフを動的に検出し、ガベージコレクションに使用できます。
私の知る限り、ガベージコレクタなしでJavaを記述することはできません。ちょっとした検索でこれが判明しました。
JavaとC / C ++の主な違いは、C / C ++では常に選択できるのに対して、Javaでは多くの場合設計上のオプションがないことです。
以下に、Cのようなシステム言語で使用できないGC固有の問題のリストを示します。
GCは、オブジェクトを管理するコードのレベル以下で実行する必要があります。カーネルにはそのようなレベルはありません。
GCは時々マネージコードを停止する必要があります。次に、カーネルにそれを実行するとどうなるかを考えます。マシン上のすべての処理は、たとえば1ミリ秒間停止しますが、GCは既存のメモリ割り当てをすべてスキャンします。これは、厳しいリアルタイム要件の下で動作するシステムを作成するすべての試みを殺すでしょう。
GCは、ポインターと非ポインターを区別できる必要があります。つまり、存在するすべてのメモリオブジェクトを確認し、そのポインタが見つかるオフセットのリストを作成できる必要があります。
この発見は完璧でなければなりません。GCは発見したすべてのポインタを追跡できなければなりません。誤検知を逆参照すると、クラッシュする可能性があります。偽陰性の発見に失敗した場合、まだ使用中のオブジェクトが破壊され、マネージコードがクラッシュしたり、データが静かに破損したりする可能性があります。
これには、存在するすべてのオブジェクトに型情報を保存することが絶対に必要です。ただし、CとC ++はどちらも、型情報を含まない単純な古いデータオブジェクトを許可します。
GCは本質的に遅いビジネスです。Javaでソーシャル化されたプログラマーはこれに気付かないかもしれませんが、Javaで実装されていない場合、プログラムは桁違いに速くなる可能性があります。また、Javaを遅くする要因の1つはGCです。これは、JavaのようなGC化された言語がスーパーコンピューティングで使用されることを妨げるものです。マシンの消費電力が年間100万ドルの場合、ガベージコレクションにその10%を支払う必要はありません。
CおよびC ++は、考えられるすべてのユースケースをサポートするために作成された言語です。そして、ご覧のとおり、これらのユースケースの多くはガベージコレクションによって除外されています。したがって、これらのユースケースをサポートするために、C / C ++はガベージコレクションできません。