43

posix_memalign and _aligned_malloc on Windows allow to dynamically allocate an aligned chunk of memory. Is there anything similar in C++11? As far as I know, the alignas keyword only works with statically allocated objects.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user882903
  • 503
  • 1
  • 5
  • 10
  • By aligned do you mean sequential ? If yes, memory allocated with combination of `new` operator and `[]` is dynamically aligned. – Mahesh Aug 07 '11 at 16:22
  • Aligned is kind of the opposite of sequential... – Blindy Aug 07 '11 at 16:24
  • 4
    @Blindy: I wouldn't say "opposite". More like "orthogonal"? – André Caron Aug 07 '11 at 16:31
  • 3
    By aligned I mean that the address modulo the specified value is zero. For example the call posix_memalign(&ptr, 32, 1000) guarantees that the address returned in ptr is divisible by 32. I need that for allocating objects at cache line boundaries to avoid false sharing. – user882903 Aug 07 '11 at 16:36
  • 1
    I'm afraid that there is no standard C++ allocator supporting arbitrary alignments. You have to go for platform-specific allocation APIs. But this shouldn't be much of a problem if you use it in combination with the constructor/destructor-on-arbitrary-memory example I gave you. – Hongli Aug 10 '11 at 22:37
  • 1
    Typically, alignment is used to match hardware requirements. It means that the low order bits of the pointer are all 0. Alignment of 64 byte, 256 bytes, 4KiBytes, or 64KiB bytes is not unheard of. – Mark Lakata Oct 10 '14 at 00:42
  • 2
    C++17 will add the ability to specify 'custom'/over-alignment for dynamically allocated objects: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3396.htm This proposal mentioned in the top answer has been accepted into the forthcoming Standard. – underscore_d Aug 17 '16 at 19:18

7 Answers7

34

It depends on what alignment you require. For anything <= to alignof(std::max_align_t), new works as per n3242 3.7.4.1/2:

The pointer returned shall be suitably aligned so that it can be converted to a pointer of any complete object type with a fundamental alignment requirement

std::max_align_t is a complete object type with the strictest fundamental alignment.

Note that allocation of arrays of char or unsigned char but not signed char have a different rule in 5.3.4/10:

For arrays of char and unsigned char, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the strictest fundamental alignment requirement (3.11) of any object type whose size is no greater than the size of the array being created.

So new char[1]; can have an alignment of 1.

As for allocating memory with an alignment greater than alignof(std::max_align_t), C++11 provides no direct way to do this. The only reliable way is to allocate at least size + alignment bytes and use std::align to get a correctly aligned location in this buffer.

This can waste a lot of memory, so if you need a lot of these, you could create an allocator that allocates a chunk large enough for all of them and use std::align on that. Your overhead is then amortized across all of the allocations.

Your other option is to wait for http://open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3396.htm to make it into the standard.

Personally I would just write an abstraction layer over the OS provided APIs for allocating aligned memory.

Michael Spencer
  • 1,029
  • 9
  • 18
9

You can use posix_memalign/_aligned_malloc to allocate a piece of memory and then using the special 'new' operator syntax to initialize an object in that memory region. Something like this:

// Allocate raw memory for a Foo object.
void *mem;
size_t alignment = 0x1000;
size_t size = ?;
posix_memalign(&mem, alignment, size);
// Call the constructor on the allocated memory.
Foo *foo = new (mem) Foo(...);

// Now you have a useable object.
foo->some_method();

// Call destructor without freeing object memory.
foo->~Foo();
// Free raw memory.
free(foo);
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
Hongli
  • 18,682
  • 15
  • 79
  • 107
  • 1
    Thanks, right. What I am wondering is whether there is a portable replacement for posix_memalign and _aligned_malloc in C++11? – user882903 Aug 07 '11 at 16:30
  • According to the standard `malloc` and `new` should work. The `_aligned_malloc` is because MS/Intel introduced over-aligned types and ran into problems. Rather that fixing `malloc`, and risk breaking old code, we got `_aligned_malloc`. – Bo Persson Aug 07 '11 at 16:36
  • 6
    malloc doesn't support *aligning on arbitrary sizes*, which is what user882903 presumably wants. – Hongli Aug 07 '11 at 19:03
5

Take a look at std::aligned_storage and the alignas() operator. They're part of C++11, and seem to be exactly what you're looking for.

Botz3000
  • 39,020
  • 8
  • 103
  • 127
Taahir Ahmed
  • 51
  • 1
  • 1
  • 1
    30.9.7.6p2: "It is implementation-defined whether any extended alignment is supported" referring to `std::aligned_storage`. So this isn't portable either. – Ben Voigt May 12 '13 at 18:59
  • Stativ_Assert that the required align is available. – Skeen Oct 08 '13 at 18:27
4

C++03 and C++0x have operator new.

new T or new T[] guarantees to return properly aligned memory for object of type T.

new char[], new signed char[] and new unsigned char[] guarantee to return memory properly aligned for any object, so that you can use placement new on it.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 18
    These do not work for "any" object. Say, for example, an object that must be allocated at page boundaries: certainly no C++ implementation aligns all allocations to 4096 byte boundaries. It is guaranteed to support any of the standard C++ primitive types (with double usually being the most restrictive type), but most compilers/runtimes on the PC fail to support the alignment requirements of aligned SSE types (16 byte alignment) for example. The fact that the operator new doesn't take an alignment (or really, any metadata) for the type its being used for is a huge flaw in the language. – Sean Middleditch Jan 21 '12 at 09:51
  • 3
    What the Standard actually says is "any object type with a fundamental alignment requirement", which certainly falls short of *ANY* object. – Ben Voigt May 12 '13 at 19:00
  • @SeanMiddleditch: actually, it is *at least* any built-type. For the minimum alignment supported, check the [`std::max_align_t`](http://en.cppreference.com/w/cpp/types/max_align_t) type as `std::malloc` is guaranteed to return memory at least aligned to that alignment. An implementation may feel free to return a higher alignment. – Matthieu M. Jun 29 '13 at 13:45
1

For aligned memory allocated on heap I use align() implementation from http://code.google.com/p/c-plus/source/browse/src/util.h#57, because my gcc4.8 seems to not support it. Here is a sample code:

typedef float TItem;
static const int SIZE = 100;
static const int ALIGNMENT = 16;

// allocate heap storage larger then SIZE
TItem* storage = new TItem[SIZE + (ALIGNMENT / sizeof(TItem))];
void* storage_ptr = (void*)storage;
size_t storage_size = sizeof(TItem) * (SIZE + 1);
// aligned_array should be properly aligned
TItem* aligned_array = (TItem*) align(MEM_ALIGNMENT, sizeof(TItem) * SIZE, storage_ptr, storage_size);
if (!aligned_array) { throw std::bad_alloc(); }
Michal Fapso
  • 1,242
  • 1
  • 15
  • 21
0

Intel's TBB provides a portable cache_aligned_allocator, which I think you might be what you're looking for.

Jason
  • 3,777
  • 14
  • 27
-1

The C++ Standard has always guaranteed suitable alignment for any object from heap allocations- that is,

template<typename T> T* func() {
    char* buf = new char[sizeof(T)];
    return new(buf) T();
}

is guaranteed not to fail for alignment reasons.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • lol, we answered exactly the same thing at exactly the same second :) – Armen Tsirunyan Aug 07 '11 at 16:23
  • 4
    Sorry, I think my question was not precise enough. I want to explicitly specify the boundary as in the case of posix_memalign. The reason for asking is that I want to allocate small objects at distinct cache lines to avoid false sharing. – user882903 Aug 07 '11 at 16:28
  • I don't believe that you can do that. You could just manually pad the size and allocate a larger struct. – Puppy Aug 07 '11 at 16:33
  • 12
    This answer is wrong, allocation functions only support objects whose alignment requirement is no more stringent than `alignof(std::max_align_t)`. See 3.7.4.1p2 (or 5.3.4p10) and 3.11p2. That is, the object has to have "fundamental alignment". – Ben Voigt May 12 '13 at 18:56