Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are nested structures with different alignments laid out in memory?

I'm a C# developer, writing a client for a server written in C++. The server streams some arbitrary data over TCP/IP to the client, and we have to reassemble it on the other end. The server sends us first a description of the data, then the data itself.

Problematic Structure:

struct Inner_S
{
  double a;
  double b[4][4];
};

#pragma pack(1)
struct Packed_S
{
  uint8_t c;
  Inner_S d;
};

The server is telling the client that the outer structure has an alignment of 1, and the inner structure has an alignment of 8. The protocol spec says:

Alignment of fields within a streamed structure is done according to the Itanium 64-bit C++ Application Binary Interface specification (i.e. the same as a typical GNU compiler on a typical 64-bit platform).

I found the Itanium 64-bit C++ Application Binary Interface specification. I think the part I am looking for is in "Allocation of Members Other Than Virtual Bases" but I get lost in there.

On the C# side I'm reading the data stream and packing my own class with the values extracted from the structure. I need to know where exactly in the stream to look for each element of the structure.

I'm currently handling the structure this way which is wrong according to my users:

(begin structure with alignment 1)(no padding needed)(read simple value)c(begin inner structure with alignment 8)(add padding to alignment 8)0000000(read field)aaaaaaaa(begin array)(read simple value)bbbbbbbb.....

That method is supported by at least one site.

So, when I'm parsing this data, how do I handle alignment in Inner_S?

caaaaaaaabbbbbbbb.... (I think?) caaaaaaaa0000000bbbbbbbb.... (looks wrong)

like image 210
Denise Skidmore Avatar asked Oct 29 '14 22:10

Denise Skidmore


People also ask

What are the different ways of nested structure?

The structure can be nested in the following different ways: By embedded nested structure. 1. By separate nested structure: In this method, the two structures are created, but the dependent structure (Employee) should be used inside the main structure (Organisation) as a member.

How is memory allocated for structures?

Consider below example to understand how memory is allocated for structures. There are 5 members declared for structure in above program. In 32 bit compiler, 4 bytes of memory is occupied by int datatype. 1 byte of memory is occupied by char datatype and 4 bytes of memory is occupied by float datatype.

What is the use of contiguous memory location?

Always, contiguous(adjacent) memory locations are used to store structure members in memory. Consider below example to understand how memory is allocated for structures.

Does the syntax satisfy the working of the nested structure?

We will take more examples to get clarity on how the syntax satisfies the working of the nested structure. In the above example, man structure is defined inside an employee structure which is a nested structure. Members within the nested structure which is a man can be accessed using the below syntax or format.


1 Answers

As suggested by @Cameron I tried this with offsetof since this involves POD types.

#include <iostream>
#include <cstddef>
#include <cstdint>
using namespace std;

struct Inner_S
{
  double a;
  double b[4][4];
};

#pragma pack(1)
struct Packed_S
{
  uint8_t c;
  Inner_S d;
};

int main() {
    cout << "Size: " << sizeof(Packed_S) << endl;
    cout << "c offset: " << offsetof(Packed_S, c) << endl;
    cout << "d offset: " << offsetof(Packed_S, d) << endl;
    cout << "a offset: " << offsetof(Packed_S, d.a) << endl;
    cout << "b offset: " << offsetof(Packed_S, d.b) << endl;
    return 0;
}

Output

Size: 137
c offset: 0
d offset: 1
a offset: 1
b offset: 9

So using your notation the structure is packed as caaaaaaaabbbbbbbb..... Note that if you take out the #pragma pack(1) directive the compiler adds 3 bytes of padding after c.

See here

like image 90
sjdowling Avatar answered Nov 14 '22 23:11

sjdowling