0

According to this answer:

The minimal alignment is (on a given platform) the one which won't give crashes.

With GCC 8, there are two functions to get the minimal and the preferred alignment:

  • the standard alignof operator that gives the minimum alignment
  • the GNU __alignof__ function that gives the preferred alignment

For a double, the minimum alignment is 4 bytes and the preferred alignment is 8 bytes on i386 architectures. Therefore, if I correctly understood the answer I quoted above, an application that store a double at an address that is not a multiple of 4, the program should crashes.

Let's look at the following code:

#include <iostream>
void f(void* ptr) {
 double* ptr_double = (double*) ptr;
 ptr_double[0] = 3.5;
 std::cout << ptr_double[0] << std::endl;
 std::cout << &ptr_double[0] << std::endl;
}
int main()
{
 alignas(__alignof__(double)) char arr[9];
 f(arr+1);
 return 0;
}

However, if I compile it with -m32 option, it runs well and I get the following results:

3.5
0xffe41571

We can see my double is misaligned but the program runs without any problem.

The very next sentence of the quote above is:

On x86-64 it is one byte.

In some ways, it seems to be true because my code works. But, in this case, why alignof returns 4?

Where is the problem, here? Is the given definition of the minimum alignment is wrong? Or is there something I don't get?

asked Jul 2, 2020 at 12:31
9
  • 1
    Not sure if this applies to your case, but in general, if you do something that is undefined, then a crash is not guaranteed. The code may still appear to work. Commented Jul 2, 2020 at 12:34
  • 7
    the program should crashes - That's not universally true on all architectures. Behavior can include nothing, and performance degrading. Crashing is not the only option. Commented Jul 2, 2020 at 12:36
  • 1
    The answer you link to currently has 0 upvotes and several comments discussing its accuracy. It’s not clear why you believe it unquestioningly. Commented Jul 2, 2020 at 12:38
  • 2
    You are treating a char arr[9] as a double[]. C++ doesn't allow you to do that, it violates the strict aliasing rules. Commented Jul 2, 2020 at 12:46
  • 2
    You have broken general logic. A -> B does not mandatory mean !A -> !B. For example "if your engine is broken your car will not be able to drive" which does not mean "if your engine works your car will drive". Commented Jul 2, 2020 at 13:05

1 Answer 1

5

The minimal alignment is (on a given platform) the one which won't give crashes.

Therefore, if I correctly understood the answer I quoted above, an application that store a double at an address that is not a multiple of 4, the program should crashes.

You are denying the antecedent.

Just because conforming to alignment doesn't give crashes, does not mean that misalignment will give crashes.


This is what the C++ standard says:

[expr.alignof] An alignof expression yields the alignment requirement of its operand type.

[basic.align] Object types have alignment requirements ([basic.fundamental], [basic.compound]) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier.

As far as the C++ language is concerned, there are no misaligned objects, so it doesn't specify anything about their behaviour. What you're doing is accessing a non-existing object, and the behaviour of the program is undefined.


Some CPU architectures, and in particular the one that you're using1, do not crash when using misaligned memory addresses. Such operations are simply more or less slower.

But, in this case, why alignof returns 4?

Because the language implementation chose so. Presumably because it is faster than using 1 or 2, but not faster than using 8.

1 This is what the programmers reference manual of 80386 says:

Note that words need not be aligned at even-numbered addresses and doublewords need not be aligned at addresses evenly divisible by four. This allows maximum flexibility in data structures (e.g., records containing mixed byte, word, and doubleword items) and efficiency in memory utilization. When used in a configuration with a 32-bit bus, actual transfers of data between processor and memory take place in units of doublewords beginning at addresses evenly divisible by four; however, the processor converts requests for misaligned words or doublewords into the appropriate sequences of requests acceptable to the memory interface. Such misaligned data transfers reduce performance by requiring extra memory cycles. For maximum performance, data structures (including stacks) should be designed in such a way that, whenever possible, word operands are aligned at even addresses and doubleword operands are aligned at addresses evenly divisible by four. Due to instruction prefetching and queuing within the CPU, there is no requirement for instructions to be aligned on word or doubleword boundaries. (However, a slight increase in speed results if the target addresses of control transfers are evenly divisible by four.)

However, the successor architectures of i386 have introduced vector extensions which do require alignment.


In conclusion: GCC documentation has different definition for what "minimum alignment" means than Starynkevitch has.

answered Jul 2, 2020 at 12:52
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.