none
Getting class size in physical memory RRS feed

  • Question

  • Hello,

    I'd like to ask, if it's possible to get size in bytes that has each instance of my own class in physical memory. 

    I've done some searching here on MSDN Library and found operator sizeof (not usable in this case) and method Marshal.SizeOf(typeof(Class)) that should be usable, but while compiling, I do get error 

    Type 'Namespace.Class' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

    So I'd like to ask if it's possible to determine that size and how?

    Thanks for your help.

    Monday, May 30, 2011 10:30 PM

All replies

  • Hello sh00ter,

     

    1. Use the StructLayoutAttribute.

    1.1 First note that the various static Marshal methods cannot be used to determine how large an instance of a class takes up in managed memory. They are used when an instance of the class is to be copied (i.e. marshaled) to unmanaged memory by the Interop Marshaler (see section 3 below). This unmanaged memory is typically passed to an unmanaged API or a COM method.

    1.2 Concerning the "Type 'Namespace.Class' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed." error : you need to use the StructLayoutAttribute on the class, e.g. :

        [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet=CharSet.Unicode)]
        public class MyClass
        {
            public Int32 m_int;
            public Int32[] m_int_array;
            public string m_str;
        }

    This will indicate to the Marshal class how the class members are to be formatted in memory in preparation for interop marshaling.

    With this layout information the interop marshaler can then calculate the size of unmanaged memory required to hold a copy of an instance of the class. The Pack argument of the StructLayoutAttribute can also affect the overall size of this unmanaged memory.

    1.2 Thereafter, the size of an instance of the class (when copied to unmanaged memory) may be computed by using the typeof() operator or by using an actual instance of the class, e.g. :

        MyClass my_class = new MyClass();
        int iSize = Marshal.SizeOf(my_class);
        int iSize2 = Marshal.SizeOf(typeof(MyClass));

    Using the above example of MyClass, iSize and iSize2 equals 12 : "m_int" is 4 bytes in length, the next 2 members are references to other classes and they are 4 bytes each. 

     

    2. The MarshalAsAttribute.

    2.1 The MarshalAsAttribute, if applied to any of the members of the class, can also affect the overall size of an instance of the class (as it is laid out in unmanaged memory), e.g. :

        [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet=CharSet.Unicode)]
        public class MyClass
        {
            public Int32 m_int;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst=10)]
            public Int32[] m_int_array;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst=10)]
            public string m_str;
        }

    In this case, the individual contents of the "m_int", "m_int_array" and "m_str" members are laid out in memory back to back (due to Pack=1).

    "m_int" is 4 bytes long. "m_int_array" consists of 10 4-byte integers. "m_str" consists of 10 2-byte Unicode characters (due to CharSet=CharSet.Unicode). This totals 64 bytes.

     

    3. The Purpose  of the Marshal Class Methods.

    3.1 As mentioned, the StructLayoutAttribute and the MarshalAsAttribute affects how the Interop Marshaler (i.e. the Marshal class) copies the contents of an instance of a class into unmanaged memory. The Marshal.SizeOf() method is usually accompanied by code to allocate unmanaged memory and to copy an instance of a class into this unmanaged memory, typically for passing to an unmanaged API, e.g. :

                MyClass my_class = new MyClass();
                int iSize = Marshal.SizeOf(my_class);
                     ...
                // code to assign values to the members of my_class.
                     ...
                IntPtr p = IntPtr.Zero;
                p = Marshal.AllocHGlobal(iSize);
                Marshal.StructureToPtr(my_class, p, false);

    3.2 In the code above, the unmanaged memory pointed to by "p" contains data from "my_class" and is formatted in memory according to the StructLayoutAttribute and the various MarshalAsAttribute's.

    3.3 I repeat and emphasize that aside from this purpose, we cannot use the various static Marshal methods to determine how large an instance of a class takes up in managed memory.

     

    - Bio.

     

    Tuesday, May 31, 2011 12:14 AM
  • Hello,

    I'd like to ask, if it's possible to get size in bytes that has each instance of my own class in physical memory. 

    I've done some searching here on MSDN Library and found operator sizeof (not usable in this case) and method Marshal.SizeOf(typeof(Class)) that should be usable, but while compiling, I do get error 

    Type 'Namespace.Class' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

    So I'd like to ask if it's possible to determine that size and how?

    Thanks for your help.


    Well yes in fact it is possible, but it is not easy because very little of what you need is exposed by .Net.

    The size of an object instance is not trivial, every reference field in a struct or class is in fact a pointer to some other class, so asking for the size of that is not always meaningful.

    Is it important to know this "size"? if so can you explain why?

     

    Cap'n

     

    Wednesday, June 1, 2011 10:35 PM
  • Hi sh00ter,

    We have not heard from you in a couple of days.

    Please post back at your convenience if we can assist further.

    Enjoy your day!


    Min Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, June 7, 2011 2:39 AM
    Moderator