none
Does GC move array data elements or only the managed object that 'points' to the data? RRS feed

  • Question

  • If I declare an array thus:

    Point[,] array = new Point[10,10];

    and populate the array, then we know that the GC may move 'array' around as part of its routine operations.

    However, although it may move the reference object 'array' I gather that it doesn't move the 100 elements of the array itself?

    Internally the object data structure (that is 'pointed to' by 'array') is a small block of descriptive data, and that block contains a pointer (not visible, even in SOS it seems) to the array data proper.

    This seems to be true and makes sense (why have the GC move massive arrays around?) but is it dcoumented anywhere as true?

    Thanks

    Cap'n

     

    Saturday, July 3, 2010 5:27 PM

Answers

  • However, although it may move the reference object 'array' I gather that it doesn't move the 100 elements of the array itself?


    Yes, of course it can, and will, move the array itself. The GC doesn't move references. It moves the item(s) pointed to by those references and then goes and updates all the references that referenced it.

    You must pin anything you hand off to the unmanaged world.

    • Marked as answer by SamAgain Monday, July 12, 2010 10:04 AM
    Saturday, July 3, 2010 6:04 PM
  • When the GC moves an object that has a ref to some other, it doesn't necessarily move that other object, so why should an object that contains a (hidden ref?) to a contiguous data block be treated differently?
    System.Array doesn't have any fields. It is treated as an intrinsic type. Regardless, it is a reference object, and like all reference objects is a block of memory on the heap. That block is subject to being moved, so long as it isn't pinned.
    • Marked as answer by SamAgain Monday, July 12, 2010 10:04 AM
    Saturday, July 3, 2010 7:26 PM

All replies

  • However, although it may move the reference object 'array' I gather that it doesn't move the 100 elements of the array itself?


    Yes, of course it can, and will, move the array itself. The GC doesn't move references. It moves the item(s) pointed to by those references and then goes and updates all the references that referenced it.

    You must pin anything you hand off to the unmanaged world.

    • Marked as answer by SamAgain Monday, July 12, 2010 10:04 AM
    Saturday, July 3, 2010 6:04 PM
  • However, although it may move the reference object 'array' I gather that it doesn't move the 100 elements of the array itself?


    Yes, of course it can, and will, move the array itself. The GC doesn't move references. It moves the item(s) pointed to by those references and then goes and updates all the references that referenced it.

    You must pin anything you hand off to the unmanaged world.


    Yes, but in the case of an array the object ref points to an object - not with instance fields - but with a pointer to where the array data is held.

    So the object (as defined inside the CLR) datum is a distinct entity from the actual array data (it seems to me).

    When the GC moves an object that has a ref to some other, it doesn't necessarily move that other object, so why should an object that contains a (hidden ref?) to a contiguous data block be treated differently?

    I'm not 100% sure though, that an array of value types is not always implemented as a physically adjacent block following the object header, in other words, it could be the case that the entire array memory block "is" in essence, a large (hidden) instance field block, in which case you'd be correct.

    Thanks

    Cap'n

     

    Saturday, July 3, 2010 6:55 PM
  • When the GC moves an object that has a ref to some other, it doesn't necessarily move that other object, so why should an object that contains a (hidden ref?) to a contiguous data block be treated differently?
    System.Array doesn't have any fields. It is treated as an intrinsic type. Regardless, it is a reference object, and like all reference objects is a block of memory on the heap. That block is subject to being moved, so long as it isn't pinned.
    • Marked as answer by SamAgain Monday, July 12, 2010 10:04 AM
    Saturday, July 3, 2010 7:26 PM
  • When the GC moves an object that has a ref to some other, it doesn't necessarily move that other object, so why should an object that contains a (hidden ref?) to a contiguous data block be treated differently?
    System.Array doesn't have any fields. It is treated as an intrinsic type. Regardless, it is a reference object, and like all reference objects is a block of memory on the heap. That block is subject to being moved, so long as it isn't pinned.


    Well I didn't mean fields in the literal explict sense.

    What I mean't was it is as if the array data block was a field, because it is situated in the object data structure in the very same place that fields go.

    All instance fields begin at a fixed offset from the start of the object instance itself, so does the array data from what I can see.

    As you know an object reference is really a pointer to a chunk of data beginning with a sync block address, the runtime type info address followed by the instance fields.

    The object ref actually point at the RTTI address, which is either 4-bytes or 8-bytes depending on whether the system is x86 or x64.

    So, the address of the first field in any managed object instance is always the address in the object ref itself + 4 (or 8).

    Well for arrays the same is true, they seem to begin with a variable (per array type) block that defines the rank and bound of the array.

    After this is a contiguous block of memory that holds every element in the array.

    This means that you were right about the GC, it must move the entire array around as a unit (I originally thought the object header held a ptr to the array data, I was wrong).

    That's all I meant by my field analogy, to all intents and purposes the array data (and rank/bounds metadata) might as well be fields.

    Cap'n

     

     

    Sunday, July 4, 2010 1:04 AM