What can I use instead of std::aligned_alloc in MS Visual Studio 2013?

為{幸葍}努か 提交于 2020-01-04 02:16:27

问题


I would like to use C++11's std::aligned_alloc, but unfortunately it isn't available with Microsoft Visual Studio 2013.

I'm considering, intsead, implementing aligned_alloc on my own. How should an implementation look like? The following for example doesn't compile, because it cannot convert from void* to void*&.

 template<typename T>
 T* aligned_alloc( std::size_t size, std::size_t align )
 {
        T* ptr = new T[size + align];
        std::align(align, size, reinterpret_cast<void*>(ptr), align + size);
        return ptr;
 }

回答1:


Disclaimer: I didn't thoroughly test this code.

void* aligned_alloc(std::size_t size, std::size_t alignment){
    if(alignment < alignof(void*)) { 
        alignment = alignof(void*); 
    }
    std::size_t space = size + alignment - 1;
    void* allocated_mem = ::operator new(space + sizeof(void*));
    void* aligned_mem = static_cast<void*>(static_cast<char*>(allocated_mem) + sizeof(void*)); 
    ////////////// #1 ///////////////
    std::align(alignment, size, aligned_mem, space);
    ////////////// #2 ///////////////
    *(static_cast<void**>(aligned_mem) - 1) = allocated_mem;
    ////////////// #3 ///////////////
    return aligned_mem;
}

void aligned_free(void* p) noexcept {
    ::operator delete(*(static_cast<void**>(p) - 1));
}

Explanation:

The alignment is adjusted to alignof(void*) if it's less than that, because, as we will see, we need to store a (properly aligned) void*.

We need size + alignment - 1 bytes to ensure that we can find a size byte block in there with the right alignment, plus an additional sizeof(void*) bytes to store the pointer returned by ::operator new so that we can free it later.

We allocate this memory with ::operator new and store the returned pointer in allocated_mem. We then add sizeof(void*) bytes to allocated_mem and store the result in aligned_mem. At this point, we haven't aligned it yet.

At point #1, the memory block and the two points look like this:

              aligned_mem (not actually aligned yet)
              V
+-------------+-----------------------------------------+
|sizeof(void*)|    size + alignment - 1  bytes          |
+-------------+-----------------------------------------+
^
allocated_mem points here

The std::align call adjusts aligned_mem to obtain the desired alignment. At point #2, it now looks like this:

                      aligned_mem (correctly aligned now)
                      V
+---------------------+---------------------------------+
| extra space         |  at least size bytes            |
+---------------------+---------------------------------+
^
allocated_mem points here

Because we started at sizeof(void*) bytes past allocated_mem, the "extra space" is at least sizeof(void*) bytes. Moreover, aligned_mem is correctly aligned for void*, so we can store a void* right before it. At point #3, the block of memory looks like this

                      aligned_mem (returned to caller)
                      V
+---------------+-----+---------------------------------+
|               |  ^  |  at least size bytes            |
+---------------+--+--+---------------------------------+
^                  |
allocated_mem      value of allocated_mem
points here        stored here

As to aligned_free, it simply reads the pointer stored there and passes it to ::operator delete.




回答2:


In Windows it's _aligned_malloc and _aligned_free, which can be found in malloc.h. The std implementation (of alignof/alignas) is in VS 2015. It's not available in 2013.



来源:https://stackoverflow.com/questions/32133203/what-can-i-use-instead-of-stdaligned-alloc-in-ms-visual-studio-2013

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!