Reputation: 41
Consider the following code, where class A is responsible for managing native data. A pointer to that data is passed to a class B, so I need that A is not collected while B is in use:
class A
{
public A(string n)
{
_n = n;
_p = IntPtr.Zero; //acquire native resource
}
public IntPtr GetP()
{
return _p;
}
~A()
{
Console.WriteLine("Free native resource {0}", _n);
}
string _n;
IntPtr _p;
};
class B
{
public B(IntPtr p)
{
_p = p;
}
public B(IntPtr p, Object o)
{
_p = p;
_o = o;
}
public IntPtr GetP()
{
return _p;
}
IntPtr _p;
Object _o;
};
If I don't hold a reference to 'a' from 'b', 'a' gets collected immediately as expected, which leaves me with a pointer to invalid data (at least in visual studio, the gc in mono is not so eager):
static void Main(string[] args)
{
var a = new A("a");
var b = new B(a.GetP());
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("b._p: {0}", b.GetP());
}
Output:
Free native resource a
b._p: 0
But if I hold a reference to 'a' from 'b', 'a' is not freed until exit, even though 'a' is not used later on:
static void Main(string[] args)
{
var a = new A("a");
var b = new B(a.GetP(), a);
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("b._p: {0}", b.GetP());
}
Output:
b._p: 0
Free native resource a
So my question is: in this second case, is 'a' guaranteed by spec to be alive while 'b' is not collected, or is this behavior implementation dependent? If the latter, how would I go about keeping it alive? I've seen several similar questions but I found no definitive answer for it.
Upvotes: 0
Views: 129
Reputation: 292405
So my question is: in this second case, is 'a' guaranteed by spec to be alive while 'b' is not collected,
Yes. If b
has a reference to a
and is not collected, a
will not be collected either.
Upvotes: 5