structure byte alighment and sockets

R

Richard Harris

Hello,


Consider this:

struct MBD {
double x;
double y;
int i;
}

Now, on my current machine, sizeof(struct MBD) = 24.

I assume this is due to byte alignment on 8 byte boundaries and the
shift of the int i to be 8 bytes, not four.

So... consider the case of socket data transmission, wherein, a client
transmits a struct MBD and it is read by a server.

It would go like this:
read(soc, (char*) address, sizeof(struct MBD));
write(soc, (char*) address, sizeof(struct MBD));

Now, IF the server and client run on the same archiecture, there
should be no problem.

But what if they run on different machines that align bytes differently?

There is now a problem.

One fix would be to find a way to supress byte alignment using a
compiler option
flag (if one exists... does one?)
Another would be to transmit the fields singly.
But these both appear to be kludge workarounds.

Am I thinking about this incorrectly?
Is there a more fundamental or comp.theoretical issue I am overlooking
with regard to the sizeof operator, or structures, or read/write?

thanks
 
J

joe

Richard Harris said:
Consider this:

struct MBD {
double x;
double y;
int i;
}

Now, on my current machine, sizeof(struct MBD) = 24.

I assume this is due to byte alignment on 8 byte boundaries and the
shift of the int i to be 8 bytes, not four.

So... consider the case of socket data transmission, wherein, a client
transmits a struct MBD and it is read by a server.

It would go like this:
read(soc, (char*) address, sizeof(struct MBD));
write(soc, (char*) address, sizeof(struct MBD));

Now, IF the server and client run on the same archiecture, there
should be no problem.

That's not really true. Even on the same architecture the programs may
have different ideas about the struct size, padding, etc if different
compilers, complier flags, pragmas, etc were used to build them.
Am I thinking about this incorrectly?
Is there a more fundamental or comp.theoretical issue I am overlooking
with regard to the sizeof operator, or structures, or read/write?

One common recommendation in this regard is to use xdr, or some other
standard marshalling/unmarshalling technique. Another is to simply
convert everything to ASCII for the transmission.

Joe
 
B

Barry Margolin

Richard Harris said:
Hello,


Consider this:

struct MBD {
double x;
double y;
int i;
}

Now, on my current machine, sizeof(struct MBD) = 24.

I assume this is due to byte alignment on 8 byte boundaries and the
shift of the int i to be 8 bytes, not four.

So... consider the case of socket data transmission, wherein, a client
transmits a struct MBD and it is read by a server.

It would go like this:
read(soc, (char*) address, sizeof(struct MBD));
write(soc, (char*) address, sizeof(struct MBD));

Now, IF the server and client run on the same archiecture, there
should be no problem.

But what if they run on different machines that align bytes differently?

Even worse, what if they have completely different ways of representing
floating point numbers.
There is now a problem.

One fix would be to find a way to supress byte alignment using a
compiler option
flag (if one exists... does one?)
Another would be to transmit the fields singly.
But these both appear to be kludge workarounds.

Am I thinking about this incorrectly?
Is there a more fundamental or comp.theoretical issue I am overlooking
with regard to the sizeof operator, or structures, or read/write?

You should generally not depend on being able to transmit binary data
directly between different computers. You need to make use of a
standard encoding; this is the job of the Presentation Layer of the OSI
model. There are some popular libraries that handle this: XDR (which is
used by Sun RPC) and ASN.1/BER are the most well known. You could also
just convert them to text and then parse them using sscanf() after
receiving them.
 
T

Thomas Matthews

Richard said:
Hello,


Consider this:

struct MBD {
double x;
double y;
int i;
}

Now, on my current machine, sizeof(struct MBD) = 24.

I assume this is due to byte alignment on 8 byte boundaries and the
shift of the int i to be 8 bytes, not four.

So... consider the case of socket data transmission, wherein, a client
transmits a struct MBD and it is read by a server.

It would go like this:
read(soc, (char*) address, sizeof(struct MBD));
write(soc, (char*) address, sizeof(struct MBD));

Now, IF the server and client run on the same archiecture, there
should be no problem.

But what if they run on different machines that align bytes differently?

There is now a problem.

One fix would be to find a way to supress byte alignment using a
compiler option
flag (if one exists... does one?)
Another would be to transmit the fields singly.
But these both appear to be kludge workarounds.

Am I thinking about this incorrectly?
Is there a more fundamental or comp.theoretical issue I am overlooking
with regard to the sizeof operator, or structures, or read/write?

thanks

My advice is not to use structures directly.
Copy the data into a buffer, in the format that you want,
then transmit it. Read the data into a buffer, extract
the data into a structure.

Here are some of the problems with using raw data structures:
1. Padding -- some compilers put it in there.
2. Floating point sizes.
3. Endianness.

My experiece is that structures are handy for lumping data
within a program. One should convert data to/from that
structure from/to the real world or outside the program's
environment.


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
B

Barry Margolin

That's not really true. Even on the same architecture the programs may
have different ideas about the struct size, padding, etc if different
compilers, complier flags, pragmas, etc were used to build them.

That's not really a problem in practice. If it were, you would have
problems calling kernel and library routines if they were compiled with
different compilers or options. So in the real world, structure layout
is part of the ABI of the system, and all compilers for a system have to
conform (there could be options or pragmas to override this, but the
kernel and general purpose libraries obviously shouldn't use them).
 
J

joe

Barry Margolin said:
That's not really a problem in practice. If it were, you would have
problems calling kernel and library routines if they were compiled
with different compilers or options. So in the real world,
structure layout is part of the ABI of the system, and all compilers
for a system have to conform (there could be options or pragmas to
override this, but the kernel and general purpose libraries
obviously shouldn't use them).

I thought he was talking about sending his own structs through the
net. In that case the compiler options would have an effect. For
example:

$ cat test.c
#include <stdio.h>

struct X
{
char c;
int i;
};

int main ()
{
struct X x;
printf("sizeof x = %d\n", sizeof x);
}

$ gcc test.c
$ a.out
sizeof x = 8

$ gcc -fpack-struct test.c
$ a.out
sizeof x = 5

Joe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top