devxlogo

Probe and Modify Your Types’ Alignment Programmatically

Probe and Modify Your Types’ Alignment Programmatically

he alignment requirement of your target platform is usually transparent. However, when you need to send or receive objects via a network connection, serialize objects, design heterogeneous containers, or construct different types of objects on a pre-determined memory address, there’s no escape from poking into your compiler’s alignment scheme. With the addition of alignment facilities to C++0x, probing and overriding the default alignment of your types becomes simpler, portable, and more intuitive.


Your program needs to be able to determine the alignment of a certain type and tweak it if necessary. How do you do that without resorting to non-portable and risky hacks?


Use the new alignof and alignaskeywords to detect and modify the alignment of a given type.

Presenting the Problem
Suppose you’re writing a class that has to be used by various clients, each running on a different platform. The default alignment of your target machine is four bytes. However, some of your clients use 64-bit RISC architectures with a fundamental alignmentrequirement of 16 bytes:

class Session //must have 16 byte alignment{ long long timestamp; uid_t client_id; int authorizations; bool active;public: Session(); //...};

A uniform alignment value for Session will ensure that every client will reconstruct a Sessionobject correctly from the same stream of bytes. A uniform alignment value will also enable you to serialize sessions into a file or store them in a remote database.

In C++03, the only way to ensure a uniform alignment value on every target platform is by using compilation flags and attributes. The problem is that compilation flags and attributes aren’t portable, to say the least. Additionally, they complicate the deployment and maintenance of your apps, and clutter up your code.

Incompatible alignment values are a common problem. These lead to linkage errors (because the size of a class is encoded in its mangled name), or worse, runtime crashes and buffer overflows.

Two new keywords: alignas and alignofwere recently added to the C++0x standard. Let’s see how you can use them to control the alignment of Session.

Fundamental Alignment Value
Alignment is the property of a memory address. When a certain type is said to have a four byte alignment, the compiler, linker and the built-in allocation functions of C++ will allocate objects on memory addresses that are properly aligned for that type. The new proposal introduces two concepts: fundamental alignment and extended alignment. A fundamental alignment is represented by an alignment value less than or equal to the greatest alignment supported by the implementation in all contexts. This value is equal to alignof(std::max_align_t). The fundamental alignment of a typical 32-bit Windows XP machine running on Intel 32-bit hardware is four bytes. An extended alignment is represented by an alignment value greater than the fundamental alignment of the target implementation. For example, Session has an extended alignment on 32-bit Windows XP.

Having introduced the necessary technical jargon, let’s see first how you can detect the fundamental (i.e., default) alignment of Session. You can then use that information to decide whether you need to override the fundamental alignment explicitly.

The operator alignof(T) takes a type T as its sole argument and returns an integral constant of type std::size_t that is the alignment value of T:

cout

The output will reveal the fundamental alignment of Session on your machine. It's unlikely that all target platforms will report the same value. Some platforms will display four, others might display 16 and there are also super-computers that have fundamental alignment value of 64 bytes. Now, let's see how to enforce a cross-platform uniform alignment value.

Forcing an Alignment Value
Class Session is an epicurean bed situation: it can't have an alignment that is weaker (smaller) than 16 bytes, nor can it have an alignment value that is stricter (bigger) than 16 bytes. To guarantee a 16 byte alignment value, use the alignas(n) operator. alignastakes a positive integral constant expression that indicates the desired alignment value:

alignas(16) class Session{ long long timestamp; uid_t client_id; int authorizations; bool active;public: Session(); //...};

An invalid alignment value or a value that isn't supported by the target implementation will cause a compilation error.

An expression of the form alignas(T) has the same effect as alignas(alignof(T)). Therefore, you can assign an alignment value of type T to another type U without having to guess what the alignment of T is. For example, if you want to allocate an array of char (which by default has an alignment value of 1) with an alignment value that will suit class Session, allocate the chararray like this:

unsigned char alignas(Session) buff[sizeof(Session)];

The line above declares an array of unsigned char called buff, which has the alignment requirement of class Session. This means that you can safely construct a Session object on buffalthough the array is allocated on the stack:

Session *p = new(buff) Session; 

This technique solves an onerous problem from which automatic char arrays have always suffered. In C+03, there's no guarantee that a char array allocated on the stack shall have the right alignment for accommodating any other objects but char, as opposed to pointers returned from malloc() and new[] (the latter are fundamentally aligned to suit any type). This is why all normative examples of placement new use dynamically-allocated buffers instead of automatic arrays. With the introduction of operator alignas, it's now possible to allocate any type of objects on an automatic chararray. Hooray!

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist