When calling a function in a DLL or .so why is passing structs reliable when compilers do their own struct layout with alignment and padding?

Viewed 80

AFAIK in c-language structs get laid out, aligned and padded as the compiler sees fit. That is why you cannot rely on one c-program to use structs from another c-program. E.g. you cannot save a struct as a binary file that another c program will read and cast to that same struct. You may be able to use packed structs like that but that's not really good practice.
So I was surprised to learn that .so and DLL files have c functions that take complicated struct's (references thereof) as their parameters. At least my company's products do this. Is this reliable, is it good practice? Is there some new standard for struct layout with sizes, alignment and padding all being the same?

I know a 64-bit program cannot call a 32-bit library, but still I thought struct layout can vary amongst compilers of the same bits.

1 Answers

For a given processor type and a given operating system, there is usually a standard ABI (application binary interface) which specifies things such as:

  • The width and endianness of integer types.
  • The width and representation of floating-point types.
  • Alignment constraints, which dictate the presence of padding in structures.
  • How parameters are passed to functions (in registers and on the stack).

For example, on the x86_64 processor architecture (i.e. the processor architecture of 64-bit PC), there are two popular ABIs: the Microsoft x64 calling convention, used on Windows, and the System V amd64 ABI (PDF — the part you're asking about specifically is in §3.1 “Machine interface”), used everywhere else. 32-bit x86 historically had more fragmentation.

So generally, if you use different compilers for the same platform (processor and operating system) in their default mode, they'll produce the same layouts for structs, and they'll generate function calling code that's compatible with how functions compiled by other compilers read their arguments. Problems arise when you mix different platforms, for example writing a struct on an embedded device and trying to read it on a PC.

Related