Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this code produces invalid alignment with MSVC?

I have tested this code on ideone.com and it outputs 16 as it should. However when I try it in Visual Studio 2013 it shows 8. Is it a bug or lack of C++11 support from the compiler?

#include <iostream>
#include <type_traits>
using namespace std;
using float_pack = aligned_storage<4 * sizeof(float), 16>::type;
int main() {

    cout << alignment_of<float_pack>::value << endl;
    return 0;
}

I have used alignment_of because MSVC doesn't support alignof.

Edit: I see that I can't get 16 alignment with aligned_storage. But why this snippet is ok?

#include <iostream>
#include <type_traits>
#include <xmmintrin.h>
using namespace std;

__declspec(align(16)) struct float_pack {
    float x[4];
};

int main()
{
    cout << alignment_of<float_pack>::value << endl;
}

Output is 16. Does that mean that compiler can provide larger alignment when using extensions? Why I can't achieve the same result with aligned_storage? Only because MSVC doesn't provide that with aligned_storage?

like image 483
Nazar554 Avatar asked Jun 04 '14 19:06

Nazar554


People also ask

What is the default number for alignment in C++?

The /ALIGN option specifies the alignment of each section within the linear address space of the program. The number argument is in bytes and must be a power of two. The default is 4K (4096). The linker issues a warning if the alignment produces an invalid image.

Is it possible to modify the alignment of a section?

Unless you're writing an application such as a device driver, you shouldn't need to modify the alignment. It's possible to modify the alignment of a particular section with the align parameter to the /SECTION option. The alignment value that you specify can't be smaller than the largest section alignment.

Why does the C programming language have alignment rules?

This differentiation still exists in current CPUs, and still some have only instructions that perform aligned accesses. To take into account this issue, the C standard has alignment rules in place, and so the compilers exploit them to generate efficient code whenever possible.

How do I set the alignment value in bytes?

The alignment value in bytes. The /ALIGN linker option specifies the alignment of each section within the linear address space of the program. The number argument is in bytes and must be a power of two. The default is 4K (4096). The linker issues a warning if the alignment produces an invalid image.


2 Answers

It looks like std::max_align_t is 8, see it live:

std::cout << alignment_of<std::max_align_t>::value << '\n';

In the draft C++ standard section 3.11 Alignment it says:

A fundamental alignment is represented by an alignment less than or equal to the greatest alignment sup- ported by the implementation in all contexts, which is equal to alignof(std::max_align_t) (18.2).[...]

Which says that that is the max alignment the implementation supports, this seems to be backed up by this boost doc which says:

An extended alignment is represented by an alignment greater than alignof(std::max_align_t). It is implementation-defined whether any extended alignments are supported and the contexts in which they are supported. A type having an extended alignment requirement is an over-aligned type.

max_align_t is by the standard tied to the fundamental alignment which James as informed us is 8 bytes. Whereas an extension does not have to stick to this as long as it is documented which if we read the docs for __declspec align we see that it says:

Writing applications that use the latest processor instructions introduces some new constraints and issues. In particular, many new instructions require that data must be aligned to 16-byte boundaries. Additionally, by aligning frequently used data to the cache line size of a specific processor, you improve cache performance. For example, if you define a structure whose size is less than 32 bytes, you may want to align it to 32 bytes to ensure that objects of that structure type are efficiently cached.

[...]

Without __declspec(align(#)), Visual C++ aligns data on natural boundaries based on the size of the data, for example 4-byte integers on 4-byte boundaries and 8-byte doubles on 8-byte boundaries. Data in classes or structures is aligned within the class or structure at the minimum of its natural alignment and the current packing setting (from #pragma pack or the /Zp compiler option).

like image 190
Shafik Yaghmour Avatar answered Sep 28 '22 20:09

Shafik Yaghmour


std::aligned_storage defines a type of size Len, with the alignment requirement you provide. If you ask for an unsupported alignment, your program is ill-formed.

template <std::size_t Len, std::size_t Align
    = default-alignment > struct aligned_storage;

Len shall not be zero. Align shall be equal to alignof(T) for some type T or to default-alignment.

The value of default-alignment shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len (3.9). The member typedef type shall be a POD type suitable for use as uninitialized storage for any object whose size is at most Len and whose alignment is a divisor of Align.

[ Note: A typical implementation would define aligned_storage as:

template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
    typedef struct {
        alignas(Alignment) unsigned char __data[Len];
    } type;
};

—end note ]

And for alignas:

7.6.2 Alignment specifier [dcl.align]

1 An alignment-specifier may be applied to a variable or to a class data member, but it shall not be applied to a bit-field, a function parameter, the formal parameter of a catch clause (15.3), or a variable declared with the register storage class specifier. An alignment-specifier may also be applied to the declaration of a class or enumeration type. An alignment-specifier with an ellipsis is a pack expansion (14.5.3).
2 When the alignment-specifier is of the form alignas( assignment-expression ):
— the assignment-expression shall be an integral constant expression
— if the constant expression evaluates to a fundamental alignment, the alignment requirement of the declared entity shall be the specified fundamental alignment
— if the constant expression evaluates to an extended alignment and the implementation supports that alignment in the context of the declaration, the alignment of the declared entity shall be that alignment
— if the constant expression evaluates to an extended alignment and the implementation does not support
that alignment in the context of the declaration, the program is ill-formed — if the constant expression evaluates to zero, the alignment specifier shall have no effect
— otherwise, the program is ill-formed.

like image 32
Deduplicator Avatar answered Sep 28 '22 19:09

Deduplicator