2

In order to test some scenarios that interact with unmanaged code, I need to force the GC to move an object in memory.

I have the following code to test object movement. What code should be written in the section somehow force gc to move mc so that two different addresses are printed to the console?

[StructLayout(LayoutKind.Sequential)]
class MyClass
{
    public int i;
}

class Program
{
    static void Main(string[] args)
    {
        MyClass mc = new MyClass();

        // print address of mc
        var handle = GCHandle.Alloc(mc, GCHandleType.Pinned);
        Console.WriteLine(handle.AddrOfPinnedObject());
        handle.Free();

        // somehow force gc to move mc

        // print new address of mc
        handle = GCHandle.Alloc(mc, GCHandleType.Pinned);
        Console.WriteLine(handle.AddrOfPinnedObject());
        handle.Free();
    }
}
tcb
  • 4,408
  • 5
  • 34
  • 51
  • You can't. By design the GC abstracts away control over managing the memory. It's whole purpose is to prevent you from having fine grained control over how your memory is managed. – Servy Jun 18 '15 at 17:00
  • 1
    You should very much avoid needing this. – H H Jun 18 '15 at 17:30
  • There are two dedicated MDAs for that, explicitly intended to flush out these kind of bugs. https://msdn.microsoft.com/en-us/library/ya4zeek2(v=vs.110).aspx – Hans Passant Nov 14 '16 at 13:16

1 Answers1

1

I had similar "problem" and I came up with a "solution". I am aware that this code is weird and should never be put in production but it is good enough for testing when you want to make sure that your interop code handles memory re-allocations correctly.

var firstData = new int[10000];
var data = new int[50];

GCHandle handle;

handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Console.WriteLine(handle.AddrOfPinnedObject());
handle.Free();

firstData = null;
GC.AddMemoryPressure(10000000);
GC.Collect();
GC.RemoveMemoryPressure(10000000);

handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Console.WriteLine(handle.AddrOfPinnedObject());
handle.Free();
sluki
  • 524
  • 5
  • 15