Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do structs add any overhead to instance size?

Tags:

c#

.net

pinvoke

Specifically, if I make a struct that has a single field, that essentially acts as a wrapper around that value, is it safe to pass this struct to a P/Invoke method expecting the underlying type?

I'm working with a native library whose API involves a lot of pointer-to-struct types, and I'd like to use something a bit more typesafe than IntPtr to keep them all straight, by wrapping IntPtr in a generic struct. Would that work? (And has it already been done?)

like image 815
Mason Wheeler Avatar asked Jul 27 '15 10:07

Mason Wheeler


People also ask

Do structs overhead?

No. The size of all the types in the struct , and thus the offset to each member from the beginning of the struct , is known at compile-time, so the address used to fetch the values in the struct is every bit as knowable as the addresses of individual variables.

Does structure bring additional overhead to program?

No. Struct does not add any size, or have any overhead in the compiled C. It is a layer of syntax that requires additional work by the compiler, but has no overhead at runtime.

Do structs take up memory?

Yes except for padding. The struct occupies one "area" in memory. I say "area" because this is poorly defined in C due to manual memory management. Each item in the struct comes after the previous one, but there may be padding between them.

How big should a struct be C#?

From what I've read, a struct should only be used if it's 16 bytes or less; otherwise it should be a class.


2 Answers

Don't pass it as a struct, then.

Instead of figuring out how to do this directly with P/Invoke, just keep the P/Invoke methods private, and expose public methods that will take your wrapper type directly - and handle whatever you need to do to pass it forward. Your code is then only going to use these public methods without having to worry about unsafe structures :)

Mixing different types and expecting them to magically work is a recipe for disaster. Make yourself explicit, and don't rely on hiding and implicit forced casts.

The best thing about this is that it allows you to very easily use some pointer wrapper that is actually safe - you can keep it as a reference, and if it's ever lost, you can use a finalizer to dispose of the unmanaged resource as needed. Have a look at how SafeHandle and it's descendants work for a great sample.

like image 197
Luaan Avatar answered Oct 15 '22 14:10

Luaan


So long as you use LayoutKind.Sequential, then the struct's single field will be located at offset zero. Therefore, your assumption is correct.

I presume that by pointer-to-struct type, you mean an opaque pointer. The struct is forward declared but never defined. However, in that case I cannot see how declaring a struct in your C# code can really help you. An opaque pointer is, well, opaque. Only the library implementation knows how to allocate it. You can't allocate it in the consumer.

Update

Perhaps you want to wrap an opaque pointer in a struct like this:

[StructLayout(LayoutKind.Sequential)]
struct FooHandle
{
    IntPtr handle;
}

// and so on for other handle types

Interop with this struct will be indistinguishable from interop with IntPtr.

like image 36
David Heffernan Avatar answered Oct 15 '22 15:10

David Heffernan