web-dev-qa-db-ja.com

固定オブジェクトとは何ですか?

私はアリのメモリプロファイラを使用してメモリリークを見つけようとしていて、新しい用語で遭遇し​​ました:

ピン留めされたオブジェクト。

このオブジェクトが何であるかについての良い簡単な説明を私に与えることができますか?どのようにしてオブジェクトを固定/固定解除し、誰が固定したオブジェクトを検出できますか?

ありがとう

46
sagie

固定されたオブジェクトは、移動が許可されていないオブジェクトです。ガベージコレクターは通常、すべてのオブジェクトを「1つ以上のクラスター」に移動するという点でメモリを圧縮しています。これは、空き領域の大きなチャンクを作成することです。

これは基本的に、他の誰か(外部)がオブジェクトのメモリアドレスへのポインタを持っている場合、オブジェクトが移動したときにランダムなコンテンツを指す可能性があることを意味します。

オブジェクトを固定すると、GCは移動しないようになります。これは通常役に立たないので、PInvokeを使用する場合のように、ポインタを操作する場合にのみ意味があります。場合によっては、アドレスを構造体(メモリレイアウトの用語で)に変換する必要があり、それがクラスに実装されている場合は、それを固定する必要があります。

具体的に答えるには:

  • 誰がobiectをピン留めしたかはわかりません。
  • 固定はFIXEDステートメントで行われます。これは安全でないコードでのみ許可されています。

小切手:

http://msdn.Microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

52
TomTom

固定されたオブジェクトは、ガベージコレクターによって移動できないオブジェクトです。つまり、他の誰か(通常は管理対象外のコードの一部)が、特定のメモリアドレスにあるオブジェクトに依存しているため、そのアドレスは同じに保つ必要があります。

通常、ガベージコレクターはメモリ内のオブジェクトを再配置する自由があります。マネージコードでは、ガベージコレクターはすべての参照にアクセスできるため、オブジェクトを別の場所に自由に再マップし、そのオブジェクトへのすべての参照を更新して、実行中のコードに対してプロセスが透過的になるようにすることができます。このように、GCはプログラムのメモリを適切に整理し、必要に応じて圧縮する機能を備えています。

管理されていないオブジェクトがコードとやり取りしているとき(安全ではないセクションで)、コードの一部へのポインターがどこかにあるという状況が発生する可能性があります(たとえば、コードでアドレス指定されているメモリの一部へのポインター)。外部COM呼び出し。 COM呼び出しはオブジェクトが指定されたアドレスにあることを期待しているため、このメモリは再マップできません。したがって、それが移動された場合、GCはCOMオブジェクトにその変更を通知する方法がなく、アクセスが発生します。違反または悪い。

19
Jorge Córdoba

固定オブジェクトは、非マネージコードと通信するときに使用されます。マネージコードでは、ガベージコレクターはメモリブロックを自由に移動できます。これは、メモリブロックへのすべての参照を認識しており、それに応じてそれらを更新できるためです。

非マネージコード(Win-APIなど)と通信する場合、データまたはバッファーへのポインターが引数として渡されることがよくあります。ガベージコレクターがそのデータを自由に移動できる場合、ポインターは突然無効になります。ポインターがアンマネージコードに転送されるため、GCでポインターを更新することはできません。GCがポインターの使用場所を知ることさえできません。メモリの移動を防ぎ、アンマネージコードのポインタが認識できる場所にデータが留まるようにするには、オブジェクトをピン留めにすることができます。

6
Anders Abel

オブジェクトを固定する理由は、アンマネージコードを呼び出す場合です。

ガベージコレクターを実行すると、不要になったオブジェクトが削除されることがあります。これにより、ヒープに空き領域の「穴」が残ります。次に、GCは残りのオブジェクトを一緒に移動してヒープを圧縮し、空き領域が1つの連続したブロック内にあることを確認します(ハードディスクの最適化に少し似ています)。

また、圧縮の一部として移動されたオブジェクトへの(マネージコード内の)すべての参照を更新します。

アンマネージコード(たとえば、一部の外部C++)で作業していて、オブジェクトへのポインターを与えている場合、GCがアンマネージコードに、実行後にオブジェクトが移動したことを通知する方法はありません。したがって、外部コードとの共有オブジェクトをピン留め済みとしてマークして、ポインターが無効になるという問題が発生しないようにすることができます。

6
Paolo

オブジェクトを固定するには、 fixed キーワードを使用できます。

Fixedステートメントは、ガベージコレクターが可動変数を再配置することを防ぎます。 fixedステートメントは、安全でない状況でのみ許可されます。

以前に見た例では、長い値をバイトに分割して、シリアルキーにエンコードできるようにしています。これは、ポインタを取得するために nsafe コンテキストで行われました。ガベージコレクションが個々のバイトを取得するプロセスの途中で発生するため、断続的なエラーが発生し始めました。値は再配置され、正しいバイトとガベージバイトの半分が残りました。

私たちにとっての解決策は BitConverter クラスを使用することでした。 BitConverterクラスの基になるコードを見ると、変数からバイトを取得する際に、fixedキーワードを使用してバイト配列を固定していることがわかります。

5

固定されたオブジェクトとは、メモリ内の場所が設定されているオブジェクトです。

通常、ガベージコレクターはマネージヒープを圧縮し、メモリ内のオブジェクトの場所を変更します。作成したC#オブジェクトを参照するアンマネージコードがある場合は、メモリの場所を完全に参照できるようにしたい場合があります。オブジェクトを固定すると、確実にこれを行うことができます。

fixedステートメントを使用して作成できます: http://msdn.Microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

4
JonC

msdnから取得「ピン留めされたオブジェクトは、ガベージコレクターがメモリ内で移動できないオブジェクトです」

http://msdn.Microsoft.com/en-us/library/x2tyfybc(VS.71).aspx

2
CliffC