3

大規模なデータセットを処理する高性能メソッドを作成するとします。開発者がCまたはC++への移行を強制されるのではなく、手動のメモリ管理をオンにする機能を持たないのはなぜですか?

void Process()
{
    unmanaged
    {
        Byte[] buffer;
        while (true)
        {
            buffer = new Byte[1024000000];

            // process

            delete buffer;
        } 
    }   
}
4

6 に答える 6

13

メモリ ブロックへの参照がまだ存在する可能性があるときにメモリ ブロックを手動で削除できるようにすると (ランタイムは GC サイクルを実行しないとそのことを認識できません)、ダングリング ポインターが生成され、メモリの安全性が損なわれる可能性があるためです。GC 言語は、一般的に設計上メモリセーフです。

とはいえ、特に C# では、すでにやりたいことを実行できます。

void Process()
{
    unsafe
    {
        byte* buffer;
        while (true)
        {
            buffer = Marshal.AllocHGlobal(1024000000);

            // process

            Marshal.FreeHGlobal(buffer);
        } 
    }   
}

C/C++ の場合と同様に、C# では生のポインター型に対して完全なポインター演算があることに注意してください。buffer[i]つまり、buffer+i有効な式です。

于 2009-12-08T17:45:29.497 に答える
3

高性能で詳細な制御が必要な場合は、CまたはC++で実行していることを記述してください。すべての言語がすべてのものに適しているわけではありません。

追加するために編集:単一の言語がすべてのものに適しているわけではありません。すべての優れたプログラミング言語ですべての便利な機能を合計すると、矛盾を回避できたとしても、C++よりもはるかにひどい混乱を招くことになります。

機能は無料ではありません。言語に機能がある場合、人々はそれを使用する可能性があります。新しいC#手動メモリ管理ルーチンを学習しないと、C#を十分に学習することはできません。コンパイラチームは、有用な他のコンパイラ機能を犠牲にして、それを実装しようとしています。言語はCやC++のように解析が難しくなる可能性があり、そのためコンパイルが遅くなります。(C ++の人として、C#プロジェクトの1つをコンパイルすると、いつも驚かされます。コンパイルはほとんど瞬時に思えます。)

機能は、時には予期しない方法で互いに競合します。Cポインターがエイリアス化されている可能性があるため、一部の最適化が妨げられるため、C90は行列計算でFortranほどうまく機能しません。言語でポインタ演算を許可する場合は、その結果を受け入れる必要があります。

手動のメモリ管理を可能にするC#拡張機能を提案していますが、いくつかのケースではそれが役立ちます。つまり、メモリは別々の方法で割り当てる必要があり、手動で管理されたメモリと自動で管理されたメモリを区別する方法が必要になります。突然、メモリ管理が複雑になり、プログラマーが失敗する可能性が高くなり、メモリマネージャー自体がより複雑になります。すべてのケースでより複雑になり、メモリ管理が遅くなる代わりに、いくつかのケースで重要なパフォーマンスが少し得られます。

いつか、スクリプトから数値計算まで、ほとんどすべての目的に適したプログラミング言語が登場するかもしれませんが、その近くに人気のあるものはありません。それまでの間、1つの言語のみを使用するという制限、または複数の言語を学習してそれらを切り替えるという課題を喜んで受け入れる必要があります。

于 2009-12-08T17:41:50.667 に答える
0

投稿した例では、バッファを消去して再利用してみませんか?

于 2009-12-08T17:42:22.710 に答える
0

.NET ガベージ コレクターは、参照されなくなったオブジェクトを特定し、関連するメモリを適切なタイミングで解放するのに非常に優れています。実際、ガベージ コレクターには、このような大きなオブジェクトを配置する特別なヒープ (大きなオブジェクト ヒープ) があり、それらを処理するために最適化されています。

これに加えて、参照を明示的に解放できないようにすることで、メモリ リークやダングリング ポインターを伴う多数のバグが単純に取り除かれ、コードがより安全になります。

于 2009-12-08T17:46:24.700 に答える
0

同じ理由で、ほとんどのカーネルでは独自のスレッドをスケジュールできません。99.99% 以上の時間は実際には必要ないため、残りの時間でその機能を公開しても、潜在的にばかげた/危険なことをしたくなるだけです。

細かいメモリ制御が本当に必要な場合は、コードのそのセクションを別のものに記述します。

于 2009-12-08T17:59:56.223 に答える
0

明示的なメモリ管理を備えた言語で行われるように、未使用の各ブロックを個別に解放することは、ガベージ コレクターに任せるよりもコストがかかる可能性があります。これは、GC がコピー スキームを使用して、生き残ったブロックの数に比例して時間を費やす可能性があるためです (または各デッドブロックを処理する必要はありません。

于 2009-12-08T17:48:27.230 に答える