5

ここでは、C#の安全でない機能を使用しようとしています:http://ideone.com/L9uwZ5

私は、C#でのそのような方法が最悪であることを知っています。そして、このトピックにいくつかの情報があることを認めたいと思います。「倒錯」という言葉を見てください。

純粋なCの方法(C ++でさえも)のようにC#でクイックソートを実装したいと思います。クレイジーかもしれませんが、安全でないC#の可能性を深く調べたいだけです。

私はいつもstackalloc演算子を使おうとしていました。これはヒープからではなくスタックからの割り当てであることがわかっているため、プログラムの実行に失敗します。

しかし、このプログラムで例外/エラーが見られなかったとき、私は混乱しました。

  • 明示的な例外/エラーが発生しなかったのはなぜですか?

また、コードのコメント部分を見ると、次のようになります。

struct Header
{
    internal int* data;
};

Header* object_header = stackalloc Header[sizeof(Header)];
object_header->data = stackalloc int[length];

最後の行でコンパイルできません。C#コンパイラは、この式ではstackallocを使用できなかったことを通知します。なんで?データはint *型ですが、なぜここでエラーが発生したのですか?

スタックフレームだけを使用し、ヒープは使用しないようにします。別の方法があることは知っていますが、それはヒープからの割り当てです。

int*[] data = new int*[length * sizeof(int)];
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(length * sizeof(int)));
Marshal.WriteInt32(result, 0);
for(int i = 0; i < length * sizeof(int); i++) d[i] = (int*)result;

たとえば、スタック割り当てではありません。

C#言語のスタック割り当てとpure-Cスタイルの構文を使用して、倒錯タスクを明示的に解決するにはどうすればよいですか。

そのC#はそのような目的のために作成されたものではなく、そのような機能はばかげています-私は知っていますが、主な質問は重要性についてではなく、そのような機能についてです。

4

2 に答える 2

5

マークは回避策を示しました。これが必要な理由を説明しようと思います。事実上、アンマネージコードを記述していますが、メソッドは依然として非常にマネージドメソッドです。ILからマシンコードにコンパイルされ、そのスタックフレームとCPUレジスタがガベージコレクタによってオブジェクト参照を検索されます。

ジッタは、メソッドをコンパイルするときに2つの重要な役割を果たします。1つは明白で非常に目立ち、ILをマシンコードに変換します。しかし、別の非常に重要なタスクがあり、それは完全に見えません。メソッドのメタデータを生成します。スタックフレームのどの部分にオブジェクト参照が含まれ、どの部分にポインターと値型の値が格納されているかを示す表。そして、コードのどのポイントで、CPUレジスタがオブジェクト参照を格納します。また、メソッドコードのどの時点で、オブジェクト参照がスコープ外になります。GC.KeepAlive()の理由は、コードをまったく生成しない非常にユニークなメソッドです。

ガベージコレクタは、オブジェクト参照を確実に見つけるためにそのテーブルを必要とします。ただし、このテーブルには1つのレベルの間接参照しかありません。object_headerに割り当てられたスタックスペースを記述し、ポインタとポイントされたスタック領域を「オブジェクト参照をスキャンしない」とマークできます。object_header-> dataを直接割り当てる場合、スタックスペースのチャンクを記述することはできません。スタックをより小さなセクションに分割し、ヘッダーを記述するための余分な間接参照はありません。ダミーのローカル変数を使用すると、問題が解決します。

于 2012-11-26T15:20:26.333 に答える
3
于 2012-11-26T12:38:24.773 に答える