C#指针和值类型变量的重定位
C# pointer and relocation of value type variables
我写了以下不安全的 class,它包装了一个指向 int 的指针:
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 on fixed ,看起来所有对指针的操作都应该在语句中完成:
Without fixed, pointers to movable managed variables would be of
little use since garbage collection could relocate the variables
unpredictably.
那么,是否有可能在我调用值 属性 时指针对象已在内存中重新定位,而我的指针指向其他对象?我知道如果指针超出范围我会遇到问题,但我会通过我如何使用我的 class 来解释它。所以我问的是 relocating 值类型变量 not 超出范围。
是的,很有可能,甚至很有可能。
在堆上:
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 中)确实在堆上,因此在这种情况下您应该小心处理这些变量。
我写了以下不安全的 class,它包装了一个指向 int 的指针:
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 on fixed ,看起来所有对指针的操作都应该在语句中完成:
Without fixed, pointers to movable managed variables would be of little use since garbage collection could relocate the variables unpredictably.
那么,是否有可能在我调用值 属性 时指针对象已在内存中重新定位,而我的指针指向其他对象?我知道如果指针超出范围我会遇到问题,但我会通过我如何使用我的 class 来解释它。所以我问的是 relocating 值类型变量 not 超出范围。
是的,很有可能,甚至很有可能。
在堆上:
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 中)确实在堆上,因此在这种情况下您应该小心处理这些变量。