2016-07-24 108 views
2

我寫了一個包裝了指向int以下不安全類的搬遷:C#指針和值類型變量

unsafe class PtrWrapper 
{ 
    public PtrWrapper(ref int val) 
    { 
     fixed (int* ptr = &val) 
     { 
      m_ptr = ptr; 
     } 
    } 
    public int Value 
    { 
     get { return *m_ptr; } 
     set { *m_ptr = value; } 
    } 
    int * m_ptr; 
} 

我測試過它,它似乎很好地工作,但是我剛剛再次讀取固定reference,它看起來像一個指針的所有操作應該在語句中來完成:

沒有固定,指針移動管理變量將是 沒有多大用處,因爲垃圾收集可能相對不可預知地發生變化 。

那麼,有可能在我調用Value屬性的時候,指針被重新定位在內存中,我的指針指向其他東西?我知道如果指出者超出範圍,我會遇到問題,但是我將如何使用我的課程來說明問題。所以我問搬遷的值類型變量,其而不是超出了範圍。

回答

3

是的,這是很有可能的,甚至可能。

在堆:

class M 
{ 
    public int i; 
    public PtrWrapper w; 

    public M() 
    { 
     i = 42; 
     w = new PtrWrapper(ref i); 
    } 
} 

var m = new M(); 
var value = m.w.Value; // probably 42 

// move m to gen 2 
GC.Collect(); 
GC.Collect(); 

value = m.w.Value; // probably a random value 

,這就是爲什麼它被稱爲不安全 :) fixed只是阻止一些移動,而它的範圍之內。

在堆棧上,但它應該沒問題。只有當你走出去的範圍在堆棧上的變量會被彈出,如在這種情況下:

PtrWrapper M() 
{ 
    var i = 42; 
    var w = new PtrWrapper(ref i); 
    return w; 
} 

var w = M(); 
var value = w.Value; // some random value 

注意捕捉變量(在lambda表達式)真的是在堆上,所以你要小心那些那種情況。