What happens if I pass a data member by reference to a function, and while that function is running, the Garbage Collector starts running and moves the object containing the data member in memory?
class SomeClass
{
int someDataMember;
void someMethod()
{
SomeClass.someFunction(ref someDataMember);
}
static void someFunction(ref int i)
{
i = 42;
int[] dummy = new int[1234567890];
// suppose the Garbage Collector kicks in here
i = 97;
}
}
How does the CLR make sure reference parameters don't become invalid during Garbage Collection? Are they adjusted just like class references?
Well, life is not easy for the garbage collector. But it knows how to deal with interior pointers like this. Well hidden from managed languages like C# and VB.NET, it is visible in C++ where interior pointers can easily be generated by the language syntax. Stan Lippman of C++ Primer fame has a blog post about them, giving some primary motivation for the interior_ptr
keyword available in C++/CLI.
The jitter goes one step beyond this, it marks the reference as GC_CALL_INTERIOR, indicating the specific case of an argument that may be an interior pointer. You can see how it is being handled inside the GC with the source code available from the SSCLI20 distribution. It isn't terribly complicated, a snippet from gcsmp.cpp, GCHeap::Relocate() method:
if (flags & GC_CALL_INTERIOR)
{
if ((o < gc_heap::gc_low) || (o >= gc_heap::gc_high))
{
return;
}
o = gc_heap::find_object (o, gc_heap::gc_low);
offset = (BYTE*)object - o;
}
So, in a nutshell, a very quick test to discover that it can't be a pointer that references a member of a reference type object by checking the pointer against the GC heap segment lower/upper bounds. Then a bit of digging to map the interior pointer to the object that contains the the member. Have a look at the SSCLI20 source code to see that code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With