简体   繁体   中英

Dynamic aligned memory allocation in C++11

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.

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.

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);

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.

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.

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(); }

英特尔的TBB提供了一个可移植的cache_aligned_allocator ,我认为您可能正在寻找它。

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM