2009-05-14 10 views
0

以下のC#コードがクラッシュしない理由を説明できる人はいますか? Visual Studioで実際にコンパイルできるのはなぜですか?私の理解は、私は固定ポインタを取得しているが、それは '固定'ステートメント内でのみ固定されています。ポインタが 'Foo'関数から返されると、配列 'ar'が収集されることがあります。私はGCに実際にこれを強制しますが、メモリへの連続書き込み(割り当てが解除されています)がエラーを起こさないようにします。固定ステートメント以外の固定ポインタの動作が不明確

class Program 
{ 
    static unsafe byte* Foo() 
    { 
     byte[] ar = new byte[100]; 
     fixed (byte* ptr = ar) 
     { 
      return ptr; 
     } 
    } 

    static unsafe void Main(string[] args) 
    { 
     byte* ptr = Foo(); 
     GC.Collect(); 
     for (int t = 0;;++t) ptr[t%100] = 0; 
    } 
} 

答えて

1

Ericは正しいですが、あなたが聞きたいと思う答えは、「固定ステートメントの外部にアドレスを保持すると便利なことがあります」ということです。

多分、そのポインタからのメモリは、他の固定されたステートメントによって既に固定されていて、それを返すのは理にかなっていますか?コンパイラは、あなたを推測して騒々しい警告を出そうとしていません。

つまり、コンパイラが自分の足を切ってしまわないように、CodeAnalysisやその他の高度なツールがここに入ることを願っています。

1

メモリが解放されたというだけでは、メモリへの書き込みが何らかのエラーの原因となるわけではありません。ガベージコレクタがメモリを解放すると、内部メモリマップに空きとしてマークされます。すぐにOSに返されるわけではありませんので、プロセスが使用するメモリはまだ有効です。

もちろん、固定ブロックの外側のポインタを使用すると、非常にという悪い考えではありません。

+0

しかし、コンパイル時にエラーが発生しなかった理由は分かりますか?明らかなエラーであれば、コンパイラはエラーメッセージを生成するはずです。 –

+2

「安全でない」と表示されている箇所を参照してください。それはコンパイラに "私がやっていることを知っていて、この危険なコードの型安全性について責任を負っている"と伝えています。コンパイラは、あなたが何をしているかを知っていると言ったときにあなたを信じるので警告しません。 –

関連する問題