Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class layout in C++: Why are members sometimes ordered?

Tags:

c++

The C++ standard dictates that member variables inside a single access section must be layed out in memory in the same order they were declared in. At the same time, compilers are free to choose the mutual ordering of the access sections themselves. This freedom makes it impossible in theory to link binaries created by different compilers. So what are the remaining reasons for the strict in-section ordering? And does the upcoming C++09 new C++11 standard provide a way to fully determine object layouts "by hand"?

like image 708
Koen Van Damme Avatar asked Nov 14 '08 09:11

Koen Van Damme


2 Answers

This freedom makes it impossible in theory to link binaries created by different compilers.

It's impossible for a number of reasons, and structure layout is the most minor. vtables, implementations of operator new and delete, data type sizes...

So what are the remaining reasons for the strict in-section ordering?

C compatibility, I would have thought, so that a struct defined in C packs the same way it does in C++ for a given compiler set.

And does the new C++0911 standard provide a way to fully determine object layouts "by hand"?

No, no more than the current standard does.

For a class or struct with no vtable and entirely private (or public) fields, though, it's already possible if you use the [u]int[8|16|32|64]_t types. What use case do you have for more than this?

like image 149
Sunlight Avatar answered Nov 15 '22 20:11

Sunlight


[edit] I learnt something new today! found the following standard quote:

Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

Interesting - i have no idea why this degree of freedom is given. Continuing to th rest of my previous reply...


As mentioned, the reason for preserving the ordering is C compatibility, and back then I guess noone thought of benefits of reordering members, while memory layout was typically done by hand anyway. Also, what now would be considered "ugly tricks" (like zeroing selected members with memset, or having two structs with the same layout) were quite common.

The standard does not give you a way to enforce a given layout, but most compilers provide measures to control padding, e.g. #pragma pack on MSVC compilers.

The reason for automatic padding is platform portability: different architectures have different alignment requirements, e.g. some architectures throw on misaligned ints (and these were the simple cases back then).

like image 44
peterchen Avatar answered Nov 15 '22 19:11

peterchen