5

I was wondering ,

An Instance of class is on the Heap. ( value types inside it are also in the heap).

But what about the opposite case ?

There is one question here but it didn't mention any GC related info.

So - How does GC handle this situation ?

public struct Point 
{
object o ;

   public int x, y;

   public Point(int p1, int p2) 
   {
   o = new Object();
      x = p1;
      y = p2;    
   }
}
trincot
  • 317,000
  • 35
  • 244
  • 286
Royi Namir
  • 144,742
  • 138
  • 468
  • 792

3 Answers3

7

Point includes a reference to an object on the heap. This will become eligible for collection as soon as no more copies of that Point exist with that reference. Noting that:

Point p1 = new Point(1,2);
Point p2 = p1;

is 2 copies, each with a reference to the same object on the heap. If those points are stored as fields on an object somewhere, then obviously the lifetime of the object will be at least as long as the object with those fields. If those points are only variables on the stack, then it gets more complex, because the GC may take into account whether a variable is ever read again. If it isn't, the variable might not effectively exist (or: it might).

The path can be very indirect, but it essentially comes down to: can GC get to the object, starting from the GC roots.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
3

The GC does search for object roots in

  • GC Handles (static variables are roots which are GC Handles as well)
  • All Thread Stacks
  • CPU Registers

In your case is the struct normally located inside a the thread stack and therefore searched. If it is boxed then it resides on the managed heap as a pseudo object. But you can be assured that this thing is correctly counted by the GC. Since it does contain an object it is not a blittable type anymore and cannot be passed to unmanaged code via PInvoke.

There is an issue with PInvokes if you pass a struct to it that it will be GCed even if the unmaanged call is still in progress which does get you only in release builds because for debug builds the lifetime of variables is extended until the method is left. In release mode the GC collects much more aggressively.

Edit1: Structs as members in a class objects are no special case. The GC wil inspect all class fields for class references in embedded structs as well.

Alois Kraus
  • 13,229
  • 1
  • 38
  • 64
0

A storage location of a struct type may best be thought of as a collection of storage locations fastened together with Duck® brand adhesive tape; the nature of the fastened-together storage locations will be that of the struct. If a struct is stored on the stack, its fields will be stored on the stack; if the struct is stored in a heap-object field, its fields will be stored as part of that heap object; etc. If a struct is stored in a mutable storage location, its fields (public or private) will be mutable (even if the struct does not provide for mutation, copying one struct to another will mutate the latter by overwriting its fields with the corresponding fields in the former). If a struct is stored in an immutable storage location, all of its fields will be immutable.

If you view things in that fashion, it will be easy to understand that the GC behavior of a struct is essentially the same as the GC behavior one would get by simply replacing the struct with separate fields (the only significant place the behavior is 'unusual' is with arrays, since normally an array slot just holds one item rather than a collection of fields; there is no non-struct equivalent to an array of a struct type).

supercat
  • 77,689
  • 9
  • 166
  • 211