固定バッファとは何ですか?
MSDN から:
C# では、 fixed ステートメントを使用して、データ構造内に固定サイズの配列を持つバッファーを作成できます。これは、他の言語で記述されたコード、既存の DLL または COM プロジェクトなど、既存のコードを操作する場合に便利です。固定配列は、通常の構造体メンバーに許可されている任意の属性または修飾子を取ることができます。唯一の制限は、配列型がbool、byte、char、short、int、long、sbyte、ushort、uint、ulong、float、または double でなければならないことです。
固定バッファーが でなければならない理由について、Hans Passant 氏の言葉を引用しますunsafe
。固定サイズのバッファー (配列) が安全でないのはなぜですか? 詳細については。
「固定バッファ」は実数配列ではないためです。これはカスタム値型であり、私が知っている C# 言語で値型を生成する唯一の方法です。配列のインデックス付けが安全な方法で行われたことを CLR が確認する方法はありません。コードも検証できません。これの最もグラフィックなデモンストレーション:
using System;
class Program {
static unsafe void Main(string[] args) {
var buf = new Buffer72();
Console.WriteLine(buf.bs[8]);
Console.ReadLine();
}
}
public struct Buffer72 {
public unsafe fixed byte bs[7];
}
この例では、スタック フレームに任意にアクセスできます。悪意のあるコードは、標準のバッファ オーバーフロー インジェクション手法を利用して、関数のリターン アドレスにパッチを適用し、コードを任意の場所に強制的にジャンプさせます。
はい、それは非常に危険です。
固定バッファーに非プリミティブ データ型を含めることができないのはなぜですか?
サイモン・ホワイトは有効な点を挙げました:
「コンパイラに追加された複雑さ」に行きます。コンパイラは、列挙可能な項目に適用される構造体に .NET 固有の機能が適用されていないことを確認する必要があります。たとえば、ジェネリック、インターフェイスの実装、非プリミティブ配列のさらに深いプロパティなどです。ランタイムにも、そのようなものとの相互運用の問題があることは間違いありません。
そしてイバサ:
「しかし、それはすでにコンパイラによって行われています。」一部のみ。コンパイラは、型が管理されているかどうかを確認するためのチェックを行うことができますが、固定バッファーに対して構造体を読み書きするためのコードの生成を処理しません。それは可能です (CIL レベルでそれを止めるものは何もありません)。C# で実装されていないだけです。
最後に、Mehrdad:
文字通り、固定サイズのバッファーを使用してほしくないからだと思います (マネージ コードを使用してほしいからです)。ネイティブ コードとの相互運用を簡単にしすぎると、すべてに .NET を使用する可能性が低くなり、マネージ コードを可能な限り促進したいと考えています。
答えは、「実装されていないだけです」という響きのようです。
なぜ実装されていないのですか?
私の推測では、コストと実装時間は彼らにとってそれだけの価値がないということです。開発者は、アンマネージ コードよりもむしろマネージ コードを推奨します。これは C# の将来のバージョンで実行される可能性がありますが、現在の CLR には必要な複雑さが欠けています。
別の方法として、セキュリティの問題が考えられます。固定バッファーは、コードに適切に実装されていない場合、あらゆる種類の問題やセキュリティ リスクに対して非常に脆弱であるため、C# のマネージド コードよりも固定バッファーの使用が推奨されない理由がわかります。使用を思いとどまらせたいものに多くの労力を費やすのはなぜですか?