tags:

views:

229

answers:

6

Hi, If I am creating realtively large structure how can I calculate the bytes it occupies in memory. We can do it manually , but if the struct is large enough then how to do it? Is there some code chunk or Application?

+9  A: 

You can use the sizeof operator.

But I think best way is to use the managed SizeOf function.

A good way to use this is to have a generic method or extension method like these:

static class Test
{
    static void Main()
    {
        //This will return the memory usage size for type Int32:
        int size = SizeOf<Int32>();

        //This will return the memory usage size of the variable 'size':
        //Both lines are basically equal, the first one makes use of ex. methods
        size = size.GetSize();
        size = GetSize(size);
    }

    public static int SizeOf<T>()
    {
        return System.Runtime.InteropServices.Marshal.SizeOf(typeof(T));
    }

    public static int GetSize(this object obj)
    {
        return System.Runtime.InteropServices.Marshal.SizeOf(obj);
    }
}
Shimmy
Why do you think that the `Marshal.SizeOf()` method should be used instead of the `sizeof()` keyword? Writing `sizeof(int)` is not only more effeicient than `Marshal.SizeOf(typeof(T))`, since it incurs no runtime cost, but it also is easier to read. `Marshal.SizeOf()` should only be used for types meant for use in unmanaged scenarios (such as P/Invoke).
Allon Guralnek
+1 but beware that this returns unmanaged size, which may or may not equal the managed size. Doesn't sound like that matters to the OP, though. Also, `sizeof` is fine since .NET 2.0, since it no longer requires `unsafe`.
Kent Boogaart
@Kent, right, but since the sizeof operator is naturally unmanaged (unlike the SizeOf method that is wrapped with managed code), it still has some restrictions, for example, it won't accept an unknown (i.e. generic) type where it doesn't have a predefined size.So for instance, the generic SizeOf function in my above example, cannot be implemented with the sizeof operator.
Shimmy
The `sizeof` operator still requires an `unsafe` context. The exception beginning with .NET 2.0 was to allow it to be used on the CTS types.
Brian Gideon
So anycase is safer to use the SizeOf function, also you can the use it against any CLR generic type.
Shimmy
@ Allon Guralnek,@Kent Boogaart,@Shimmy,@Brian GideonCan you please explain what is Managed and Umanaged Code,Size and Memory.I have asked the same question at the follwoing URL:http://stackoverflow.com/questions/3368802/what-is-the-diference-in-managed-and-umanaged-code-memory-and-size
Subhen
A: 

A struct should have a maximum size of 16 bytes. If your struct is larger than that then you should use a class.

Philip Smith
Why is this out of interest?
Chris
A very soft recommendation that is usually (Interop) totally irrelevant.
Henk Holterman
why does a struct have to have a max size of 16 bytes? I have seen many situations where a struct is mapped to a binary file and it is bigger than 16 bytes
0A0D
a `struct` is a value type and hence passed by value, not reference. The advantages of a `struct` over a `class` start to break down the larger an instance of a `struct` becomes.
Philip Smith
@Phillip: A struct containing many data members mapped to a binary file makes sense because that struct can be directly written write back to file and your data structures can now be represented in file form. This has been common form for many years and struct commonly goes over 16 bytes in C++I dont see why C# would be any different.
0A0D
@Phillip: This 16-byte rule is caveated in this link: http://stackoverflow.com/questions/2407691/c-struct-design-why-16-byte-is-recommended-size/2407743#2407743
0A0D
+1  A: 

You can use System.Runtime.InteropServices.Marshal.SizeOf() to get the size in bytes as well.

Jeff M
+3  A: 

You can either use the sizeof() keyword for user-defined structs that do not contain any fields or properties that are reference types, or use the Marshal.SizeOf(Type) or Marshal.SizeOf(object) to obtain the unmanaged size of a type or a struct that has a sequential or explicit layout.

Allon Guralnek
+1  A: 

you want to use System.Runtime.InteropServices.Marshal.SizeOf()

struct s
    {
        public Int64 i;

     }

public static void Main()
        {
            s s1;
            s1.i = 10;

            var s = System.Runtime.InteropServices.Marshal.SizeOf(s1);
        }
anishmarokey
+7  A: 

Structs have been troublesome beasts in computer engineering for a very long time. Their memory layout is very hardware dependent. To make them efficient, their members must be aligned so the CPU can read and write their values quickly without having to multiplex the bytes to fit the memory bus width. Every compiler has its own strategy of packing the members, often directed by, for example, the #pragma pack directive in a C or C++ program.

Which is okay, but rather a problem in interop scenarios. Where one chunk of code may make different assumptions about the structure layout than another chunk, compiled by a different compiler. You can see this back in COM, .NET's grandfather solution to interop programming. COM has very poor support for handling structs. It doesn't support them as a native automation type but has a workaround through the IRecordInfo interface. Which lets a program discover the memory layout at runtime through an explicit declaration of the structure in a type library. Which works okay, but is quite inefficient.

The .NET designers made a very courageous, and correct, decision to solve this problem. They made the memory layout of a struct completely undiscoverable. There is no documented way to retrieve the offset of a member. And by extension, no way to discover the size of the struct. Everybody's favorite answer, use Marshal.SizeOf() is not in fact the solution. That returns the size of struct after it is marshaled, the size you'd need to pass to, say, Marshal.AllocCoTaskMem() before you call Marshal.StructureToPtr. That arranges and aligns the struct members according to the [StructLayout] attribute that's associated with the struct. Note that this attribute isn't required for structs (like it is for classes), the runtime implements a default one which uses the declared order for the members.

One very nice side-effect of the layout being undiscoverable is that the CLR can play tricks with it. When packing the members of the struct and aligning them, the layout can get holes that don't store any data. Called padding bytes. Given that the layout is undiscoverable, the CLR can actually use the padding. It moves a member if it is small enough to fit such a hole. You'll now actually get a struct whose size is smaller than what would normally be required given the declared structure layout. And, notably, Marshal.SizeOf() will return the wrong value for the structure size, it returns a value that's too large.

Long story short, there's no general way to get an accurate value for the structure size programmatically. The best thing to do is to just not ask the question. Marshal.SizeOf() will give you a guesstimate, assuming the structure is blittable. If you need an accurate value for some reason then you could look at the generated machine code of a method that declares a local variable of the structure type and compare it to the same method without that local variable. You'll see the difference in the stack pointer adjustment, the "sub esp, xxx" instruction at the top of the method. Of course, it will be architecture dependent, you'll typically get a larger structure in 64-bit mode.

Hans Passant
+1, interesting.
Shimmy
@Hans: Are you saying that this only applies when using padding? Marshal.SizeOf() has never failed me and I don't use padding.
0A0D
@0A0D: padding is applied completely automatic, you don't normally see it. It is affected by the StructLayoutAttribute.Pack value for marshaled structures. The CLR uses a packing of 8, I think, small odds for 4.
Hans Passant
@Hans: What about struct's marshalled from C++ DLLs? I don't think this applies when using LayoutKind.Sequential. Per MSDN: "Indicates that the members of the type are to be laid out in unmanaged memory in the same order in which they appear in the managed type definition. " So the CLR shouldn't pad at all or the bits would be jumbled.
0A0D
@0A0D: as long as your are marshaling unmanaged structs you only care about the unmanaged layout of them. In which case Marshal.SizeOf() is fine and the default [StructLayout] usually gets the job done. But Marshal.PtrToStructure() is required to get a managed version of it. The P/Invoke marshaller does that automatically.
Hans Passant
@Hans: Ok, thanks.
0A0D
@Hans Passant, Thanks, But I am unsure and really curious to know the difference bettwen Managed and Un-Managed Code, Memory and Size. Asked the question at the following URL:http://stackoverflow.com/questions/3368802/what-is-the-difference-in-managed-and-unmanaged-code-memory-and-size
Subhen