我编写了以下不安全的类,它包装了一个指向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,看起来指针上的所有操作都应该在语句中完成:
如果没有修复,指向可移动托管变量的指针就是 垃圾收集可以重新定位变量 不可预知的。
那么,当我调用Value属性时,是否有可能指针被重新定位在内存中,而我的指针指向其他东西?我知道如果指针超出范围,我会遇到问题,但我会按照我如何使用我的课来解释它。所以我要求重新定位一个不已超出范围的值类型变量。
答案 0 :(得分: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
请注意,捕获的变量(在lambdas中)实际上是在堆上,所以你应该小心那个场景中的那些。