0

C++ Struct memory alignment

 1 year ago
source link: https://carlosvin.github.io/langs/en/posts/cpp-pragma-pack/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

A C++ struct is an element that groups attributes with different types so we can manipulate them all together using same reference. It is like a class with public visibility by default for functions and attributes.

If we want to work in a lower level, closer to machine, it might be useful understand how that data structure is stored in memory and how to control that mapping.

Struct example

It has two attributes: an integer (4 bytes) and a boolean (1 byte).

If we get the instance size using sizeof we should get 5 bytes size and memory would be like:

5Bytes
Figure 1. 5 bytes struct which uses 5 bytes in memory

But is not that simple, memory alignment depends on compiler and system. We will learn how to control compiler alignment policy, so we can avoid getting unexpected allocation memory sizes.

For example, in my local host, if I get the sizeof the previous structure without pragma declarations, I get a 8 bytes size. We are getting 8 Bytes instead of expected 5 Bytes because the compiler allocates more memory at the end of structure so it fits in 2n bytes blocks. Memory actually looks like:

5Bytes
Without pragma: 5 bytes structure that actually spends 8 bytes in memory
It prints structure and attributes size, in this case 4 + 1 is not 5
Executing code with pragma pack directive: We get 8 bytes instead of 5 bytes
If we want to know the exact structure size we have to specify compiler how to align the memory, to do so we have #pragma pack(n) directive.

#pragma pack directive in C++ struct

It is a preprocessor directive to indicate to compiler how to align data in memory.

Example with different memory alignment configurations
Executing code with pragma pack directive, we have different results depending of pragma value.
  1. SampleStructPack1 #pragma pack (1): It allocates 1 byte memory block, so our sample struct fits perfectly, in this case it is true that 4 + 1 = 5.

  2. SampleStructPack2 #pragma pack (2): Minimum block size is 2 bytes. Integer attribute fits because it just needs 2 blocks of 2 Bytes. Boolean attribute needs just 1 Byte, but minimum block size is 2 Bytes, that’s why total allocated memory is 6 bytes, 4 + 2 = 6.

  3. SampleStructPack4 #pragma pack (4): It is like previous one, but in this case we are wasting more memory for boolean attribute, it needs 1 Byte, but we are allocating 4 Bytes.

  4. SampleStruct (default compiler alignment): As you can see it behaves exactly like #pragma pack (4), so we can deduct it is the default compiler alignment.

Important
Why don’t we always use smallest memory alignment (#pragma pack (1)) so we can save more memory?
Warning
Because of performance loss.

Performance test

The test will allocate same number of elements in arrays for each structure type (1, 2, 4).

As you can see, the smallest memory alignment spends more time allocating and releasing memory.

Performance test source code:

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK