3
\$\begingroup\$

At work we are using Xamarin.iOS for our apps. We frequently have to fight it's disadvantages, namely it's memory leak issues where strong cyclic references keep objects alive and prevent them from being GC'ed just because someone somewhere forgot to set a property to null before discarding a view controller. We previously used reflection to iterate through all properties and fields to set them to null however our heavy use of reflection in cleanup code lead to some performance slow downs as well as bugs where someone forgot to check for value types and tried to assign null to them. Instead of going crazy with reflection I thought about just memset-ing the whole object to 0x0 like this:

public static class ReferenceDestructor
{
    /// <summary>
    /// Sets everything to <see langword="null"/>.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="target"></param>
    public static unsafe void DestroyAllReferencesUnsafe<T>(T? target) where T : class
    {
        if (target is not null)
        {
            // don't go crazy with reflection here. We just zero the whole object.
            // pin the target object in memory.
            using PinnedHandle pinnedHandle = new(target);

            // get size of managed object
            int unsafeManagedSize = Unsafe.SizeOf<T>();

            // basically get a pointer to *managed* memory.
            void* objectAddress = (void*)pinnedHandle.GCHandle.AddrOfPinnedObject();

            // Set unsafeManagedSize bytes at objectAddress to zero, zero-ing the whole object and setting all
            // properties and fields to null or 0 or whatever.
            Unsafe.InitBlock(objectAddress, 0x0, (uint)unsafeManagedSize);
        }
    }
}

Now apart from the liberal usage of unsafe and pointers, I wonder if this is a viable solution to solve the problem? Being only a four-liner it is certainly shorter than iterating over every field and property with reflection, having to deal with readonly or init-only access modifiers.

\$\endgroup\$
1
  • \$\begingroup\$ That's a pretty neat hack... if it works. Did you try it in production ;-P Anaways, could you tell me where I can find the PinnedHandle, cannot figure this one out or is it some Xamarin thingy? \$\endgroup\$
    – t3chb0t
    Dec 31 '21 at 21:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.