2016-07-24 1 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 на фиксированный еще раз, и это выглядит как все операции по указателю должно быть сделано в заявлении:

Без фиксированной, указатели на движимое управляемые переменные будут иметь мало пользы, так как сборка мусора может отн ocate переменные непредсказуемо.

Итак, возможно ли, что к моменту, когда я вызову значение 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 

Обратите внимание, что захватили переменные (в лямбды) действительно в куче, так что вы должны быть осторожны с теми, этот сценарий.

Смежные вопросы