adjusting memory alignment in a struct - c

I am aware of the memory alignment in structure but I am stumped at this implementation I came across in a project I am working on.
struct default {
uint8_t variable[((sizeof(struct dummyStructure) + 3) /4)*4] // Align on 32 bit boundary
}
It is more like a black box testing for me at the moment because I dont have access to the functions, but can anyone explain the math used here to cause this alignment to happen.

The answer to your question is that, by adding 3 to the size of dummyStructure and by taking the integer part of the result of the division by 4 to multiply by 4, you will either have:
The exact size of dummyStructure, if it is aligned to 32 bits (or any multiple of it, such as 64 bits).
Or the first multiple of 32 bits greater than the size of dummyStructure.
Therefore it will always yield a 4 bytes divisible number (32 bits alignment).
Example:
If the size of dummyStructure is 8 bytes, the result would be ((8 + 3)/4)*4 = 8.
Now if the size of dummyStructure is, lets say 11, the result would be ((11 + 3)/4)*4 = 12.
I'm just wondering why the developer decided for this, though, since dummyStructure should be always aligned according to the processor architecture.

You can decompose it:
uint8_t variable[((sizeof(struct dummyStructure) + 3) /4)*4]
You have two cases - sizeof dummyStructure is evenly dividable by 4 or not.
Example:
(sizeof(struct dummyStructure) = 12
(12 + 3) / 4 = 15 / 4 = 3
3 * 4 = 12
so return original size
(sizeof(struct dummyStructure) = 13
(13 + 3) / 4 = 16 / 4 = 4
4 * 4 = 16
so return next size evenly dividable by 4
(sizeof(struct dummyStructure) = 15
(15 + 3) / 4 = 18 / 4 = 4
4 * 4 = 16
as above
(sizeof(struct dummyStructure) = 16
(16 + 3) / 4 = 19 / 4 = 4
4 * 4 = 16
so return original size again
(sizeof(struct dummyStructure) = 17
(17 + 3) / 4 = 20 / 4 = 5
5 * 4 = 20
so return next size evenly dividable by 4
In reality this code does not align variable at 32bit address! It only allocates enough space in array to allow put there dummyStructure alligned manually.
This solution is really bad.
IMHO better solutions (of course depends what happens in code):
1) since C11
struct defaultx
{
alignas(4) int variable[sizeof(struct dummyStructure)];
};
2) gcc or clang specific
struct defaultx
{
int variable[sizeof(struct dummyStructure)];
} __attribute__((aligned(4)));
will make sure variable is aligned to 4 bytes;

Related

Why does this malloc wrapper do this to the size of the requested memory? size = (size + 3) & ~3;

I'm looking through DOOM source code and I found this line.
void *
Z_Malloc
(int size,
int tag,
void *user) {
int extra;
memblock_t *start;
memblock_t *rover;
memblock_t *newblock;
memblock_t *base;
size = (size + 3) & ~3; // Why is it doing this?
...
I see sizeof used a lot to create byte offsets, but I've never seen this.
I understand the caller of this function wants some memory allocated, but I'm at a loss why it would manipulate the size like this.
What is it doing?
size = (size+3) & ~3 rounds the size up to the nearest multiple of 4.
It does this so that all blocks are a multiple of 4 bytes long and every block starts at an address that is a multiple of 4.
This is necessary so that the placement of ints and pointers inside the block can be aligned to fit into single memory words, which makes accessing them more efficient. Some processors actually require it.
To see how the rounding works, lets say that size = 4x-a, where 0 <= a <= 3. We have:
size+3 = 4x + (3-a), where 3-a is also between 0 and 3.
~3 is a bit mask that includes all bits except 20 and 21, so the & operation will leave just the multiple of 4:
(size+3)&~3 = 4x
If you run this it will be obvious:
for(int i=0; i<30; i++)
printf("%d ", (i+3) & ~3);
Output:
0 4 4 4 4 8 8 8 8 12 12 12 12 16 16 16 16 20 20 20 20 24 24 24 24 28 28 28 28 32
It rounds up to nearest 4.
It's done like this. Performing x = x & ~3 will set the two least significant bits of x to zero. If we assume 8-bit numbers for simplicity, a 3 will be stored as 00000011, which means that ~3 will be 11111100, so performing a logical and with this number will set the last two bits to zero. This itself is a rounding down to nearest four, because 4 binary is 100. If you add 3 first it will be a rounding up instead.

Formula for memory alignment

While browsing through some kernel code, I found a formula for memory alignment as
aligned = ((operand + (alignment - 1)) & ~(alignment - 1))
So then I even write a program for this:
#include <stdio.h>
int main(int argc, char** argv) {
long long operand;
long long alignment;
if(argv[1]) {
operand = atol(argv[1]);
} else {
printf("Enter value to be aligned!\n");
return -1;
}
if(argv[2]) {
alignment = strtol(argv[2],NULL,16);
} else {
printf("\nDefaulting to 1MB alignment\n");
alignment = 0x100000;
}
long long aligned = ((operand + (alignment - 1)) & ~(alignment - 1));
printf("Aligned memory is: 0x%.8llx [Hex] <--> %lld\n",aligned,aligned);
return 0;
}
But I don't get this logic at all. How does this work?
Basically, the formula increase an integer operand (address) to a next address aligned to the alignment.
The expression
aligned = ((operand + (alignment - 1)) & ~(alignment - 1))
is basically the same as a bit easier to understand formula:
aligned = int((operand + (alignment - 1)) / alignment) * alignment
For example, having operand (address) 102 and alignment 10 we get:
aligned = int((102 + 9) / 10) * 10
aligned = int(111 / 10) * 10
aligned = 11 * 10
aligned = 110
First we add to the address 9 and get 111. Then, since our alignment is 10, basically we zero out the last digit, i.e. 111 / 10 * 10 = 110
Please note, that for each power of 10 alignment (i.e. 10, 100, 1000 etc) we basically zeroing out last digits.
On most CPUs, division and multiplication operations take much more time than bitwise operations, so let us get back to the original formula:
aligned = ((operand + (alignment - 1)) & ~(alignment - 1))
The second part of the formula makes sense only when alignment is a power of 2. For example:
... & ~(2 - 1) will zero last bit of address.
... & ~(64 - 1) will zero last 5 bits of address.
etc
Just like with zeroing out last few digits of an address for power of 10 alignments, we zeroing out last few bits for power of 2 alignments.
Hope it does make sense for you now.

Memory locations, and ranges

Say I have a struct:
struct guitar{
long guitarID;
short brand:3;
short strings: 6;
short price;
}x[5][5]; //Thanks chux
If the address of x is 0xaaa and memory is aligned at multiples of 4 then what would the address be at x[1]?
The other thing I want to know is what the range of numbers between brand and strings are now that they are affected by a bitfield?
Assuming long 8 bytes, short 2 bytes and memory is 4 bytes aligned size of struct is 8 byte + 3 bit + 6 bit + 2 byte = 8 + 4 = 12 bytes.
x[1] is nothing but &x[1][0].
If x is 0xaaa , x[1] is 0xaaa + (5 * 12) = 0xaaa + 60.
So x[1] is 60 bytes away from x.
Let's try to compute it. The first thing you need to know the size of the struct. Since the size is implementation dependent let's consider a 32-bit machine.
The first member of your structure, guitarID, has 4 bytes. Then, you have 3 bits in brand, 6 bits in strings. These 2, along with padding, make up another 2 bytes. And then, you have another 2 bytes in price. In total, your structure occupies 8 bytes.
Now, let's see how your array is stored. You have a matrix of 5 by 5 elements. In memory, it is stored linearly, like this:
x[0][0] x[0][1] x[0][2] x[0][3] x[0][4] x[1][0] x[1][1] x[1][2] x[1][3]
and so on. I don't know exactly what you mean by x[1], but I assume that you're interested in the address of x[1][0]. You can see that it has before it 5 elements, which means that is has an address with 5 * 8 = 40 bytes higher than the address of the first element. I cannot give you an absolute address as an answer, since 0xaaa which you mentioned as an address for the first element is not word aligned.

Size of struct that contains two pointers

What is the size of this struct? (32 bit system calculation. Not 64 bit.)
struct list_element
{
short data;
struct list_element* next;
struct list_element* prev;
};
I have tried calculating the size with these formulas:
(sizeof(list_element*) + sizeof(short)) + ((sizeof(list_element*) * 2)
(4 + 2) + (4 * 2) = 6 + 8 = 14
(sizeof(short)) + (sizeof(list_element*) * 2)
2 + (4 * 2) = 2 + 8 = 10
(sizeof(list_element*) + sizeof(list_element*) + sizeof(short)) + (sizeof(list_element*) * 2)
(4 + 4 + 2) + (4 * 2) = 10 + 8 = 18
(sizeof(list_element*) + sizeof(list_element*) + sizeof(short))
(4 + 4 + 2) = 10
However, they do not return the correct answer. What formula do you use to calculate the size of this struct?
Update:
My teacher says we a re ignoring data alignment... Hopefully that does not throw anyone off too much since you are used handling data alignment with your code and structs...
Update 2
Thank you for the help and the introduction to data alignment.
The answer was 10 without data alignment... Not sure why I am in such a rush to work with data alignment in C... Is it fun?
Also, the answer with data alignment is 12. As you guys explained, you have to data align the short to match the integers. Therefore, you have (2 + (2 additional bytes)) + 4 + 4 = 12.
The size of the struct is given by:
size_t size = sizeof(struct list_element);
The fact that you have two members that are pointers to the struct just means
you are adding the size of a pointer, twice. On a 32 bit build, sizeof would resolve to an additional 4 bytes per pointer, on a 64 bit build, it would result in an additional 8 bytes per pointer.
Another thing to be aware of is that the size of your struct is likely not simply the sum of the sizeof's of the individual members, as storage in a struct is often padded for alignment purposes. So, between your short, and the next member, the padding will result in additional size.
The reason I used the word likely is that if a pragma pack directive was used in your source, the packing alignment could be changed, resulting in a different value for sizeof.
Two good discussions on struct alignment padding: A general discussion here, and How to reduce memory footprint here. The second link is particularly interesting as it deals with structure alignment, padding and bit fields, and how each can affect memory usage.
Although your teacher asked to ignore data alignment, the size of that struct is 10 bytes assuming short being 2 bytes.. but actually the short size is not fixed, but at least 2 bytes!
Give a look here. Did you correctly reported the teacher question?
This will return the size of the struct:
sizeof(struct list_element);

Finding the correct size of a misaligned structure

typedef struct structA
{
char C;
double D;
int I;
} structA_t;
Size of this structA_t structure:
sizeof(char) + 7 byte padding + sizeof(double) + sizeof(int) = 1 + 7 +
8 + 4 = 20 bytes
But this is wrong , the correct is
24
. Why?
There is most likely 4 byte padding after the last ìnt.
If sizeof(double) == 8 then likely alignof(double) == 8 also on your platform.
Consider this situation:
structA_t array[2];
If size would be only 20, then array[1].D would be misaligned (address would be divisible by 4, not 8 which is required alignment).
char = 1 byte
double = 8 bytes
int = 4 bytes
align to double =>
padding char => 1+7
padding double => 8+0
padding int => 4+4
=> 24 bytes
or, simply put, is the multiple of the largest => 3 (the number of fields) * 8 (the size of the largest) = 24
my guess would be the size of int in your system is 4 Bytes, so the int must also be padded by 4 Bytes in order to achieve a word size of 8 Bytes.
total_size=sizeof(char) + 7 Byte padding + sizeof(double) + sizeof(int) + 4 Bytes padding = 24 Bytes
Good article on padding/alignment:
http://www.drdobbs.com/cpp/padding-and-rearranging-structure-member/240007649
Because of the double member it forces everything to be eight byte aligned.
If you want a smaller structure then following structure gives you 16 bytes only!
typedef struct structA
{
int I;
char C;
double D;
} structA_t;

Resources