开发者

Is it possible to share a C struct in shared memory between apps compiled with different compilers?

开发者 https://www.devze.com 2022-12-17 19:23 出处:网络
I realize that in general the C and C++ standards gives compiler writers a lot of latitude. But in particular it guarantees that POD types like C struct members have to be laid out in memory the same

I realize that in general the C and C++ standards gives compiler writers a lot of latitude. But in particular it guarantees that POD types like C struct members have to be laid out in memory the same order th开发者_如何学编程at they're listed in the structs definition, and most compilers provide extensions letting you fix the alignment of members. So if you had a header that defined a struct and manually specified the alignment of its members, then compiled two apps with different compilers using the header, shouldn't one app be able to write an instance of the struct into shared memory and the other app be able to read it without errors?

I am assuming though that the size of the types contained is consistent across two compilers on the same architecture (it has to be the same platform already since we're talking about shared memory). I realize that this is not always true for some types (e.g. long vs. long long in GCC and MSVC 64-bit) but nowadays there are uint16_t, uint32_t, etc. types, and float and double are specified by IEEE standards.


As long as you can guarantee the exact same memory layout, including offsets, and the data types have the same sizes between the 2 compilers then yes this is fine. Because at that point the struct is identical with respect to data access.


Yes, sure. I've done this many times. The problems and solutions are the same whether mixed code is compiled and linked together, or when transmitting struct-formatted data between machines.

In the bad old days, this frequently occurred when integrating MS C and almost anything else: Borland Turbo C. DEC VAX C, Greenhills C.

The easy part is getting the number of bytes for various data types to agree. For example short on a 32-bit compiler on one side being the same as int on a 16-bit compiler at the other end. Since common source code to declare structures is usually a good thing, a number of to-the-point declarations are helpful:

typedef  signed long     s32;
typedef  signed short    s16;
typedef  signed char     s8;
typedef  unsigned long   u32;
typedef  unsigned short  u16;
typedef  unsigned char   u8;
...

Microsoft C is the most annoying. Its default is to pad members to 16-bit alignment, and maybe more with 64-bit code. Other compilers on x86 don't pad members.

struct {
    int   count;
    char  type;
    char  code;
    char  data [100];
} variable;

It might seem like the offset of code should be the next byte after type, but there might be a padding byte inserted between. The fix is usually

#ifdef _MSC_VER    // if it's any Microsoft compiler
 #pragma pack(1)   // byte align structure members--that is, no padding
#endif

There is also a compiler command line option to do the same.


The way memory is laid out is important in addition to the datatype size if you need struct from library 1 compiled by compiler 1 to be used in library 2 compiled by compiler 2.


It is indeed possible, you just have to make sure that all compilers involved generate the same data structure from the same code. One way to test this is to write a sample program that creates a struct and writes it to a binary file. Open the resulting files in a hex editor and verify that they are the same. Alternatively, you can cast the struct to an array of uint8_t and dump the individual bytes to the screen.

One way to make sure that the data sizes are the same is to use data types like int16_t (from stdint.h) instead of a plain old int which may change sizes between compilers (although this is rare on two compilers running on the same platform).

It's not as difficult as it sounds. There are many pre-compiled libraries out there that can be used with multiple compilers. The key thing is to build a test program that will let you verify that both compilers are treating the structure equally.


Refer to your compiler manuals.

most compilers provide extensions letting you fix the alignment of members

Are you restricting yourself to those compilers and a mutually compatible #pragma align style? If so, the safety is dictated by their specification.

In the interest of portability, you are possibly better off ditching #pragma align and relying on your ABI, which may provide a "reasonable" standard for compliance of all compilers of your platform.

As the C and C++ standards allow any deterministic struct layout methodology, they're essentially irrelevant.

0

精彩评论

暂无评论...
验证码 换一张
取 消