在 MS Visual Studio 2013 中,我可以使用啥来代替 std::aligned_alloc?

Posted

技术标签:

【中文标题】在 MS Visual Studio 2013 中,我可以使用啥来代替 std::aligned_alloc?【英文标题】:What can I use instead of std::aligned_alloc in MS Visual Studio 2013?在 MS Visual Studio 2013 中,我可以使用什么来代替 std::aligned_alloc? 【发布时间】:2015-11-14 23:29:03 【问题描述】:

我想使用 C++11 的 std::aligned_alloc,但遗憾的是它不适用于 Microsoft Visual Studio 2013。

我正在考虑,intsead,我自己实施aligned_alloc。实现应该如何?以下示例无法编译,因为它无法从 void* 转换为 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) 不要使用new。这调用了构造函数。使用::operator new 分配内存。返回void *,不要模板化。 2) 您需要分配额外的内存来存储::operator new 返回的原始指针,以便以后可以将其用于释放。 3) Windows 有_aligned_malloc 返回 void* 有什么好处? void* 清楚地表明您正在返回分配的存储空间,而不是构造的对象。这些是分开的事情,应该分开处理。 也许std::aligned_storage 是你所需要的。 ::operator newstd::malloc 返回一个针对任何数据类型对齐的指针。 【参考方案1】:

在 Windows 中是 _aligned_malloc_aligned_free,可以在 malloc.h 中找到。 (alignof/alignas 的)std 实现在 VS 2015 中。它在 2013 年不可用。

【讨论】:

显然根据我的测试,aligned_alloc 或aligned_malloc 在vs 2017 中仍然没有实现。所以即使在vs2017 中你也必须如上所述使用_aligned_malloc。【参考方案2】:

免责声明:我没有彻底测试此代码。

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

解释:

如果小于该值,则对齐将调整为alignof(void*),因为正如我们将看到的,我们需要存储一个(正确对齐的)void*

我们需要size + alignment - 1字节来确保我们可以在其中找到一个正确对齐的size字节块,再加上一个额外的sizeof(void*)字节来存储::operator new返回的指针,以便我们可以释放它稍后。

我们用::operator new 分配这块内存并将返回的指针存储在allocated_mem 中。然后我们将sizeof(void*) 字节添加到allocated_mem 并将结果存储在aligned_mem 中。此时,我们还没有对齐它。

在点#1,内存块和两个点看起来像这样:

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

std::align 调用调整 aligned_mem 以获得所需的对齐方式。在第 2 点,它现在看起来像这样:

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

因为我们从sizeof(void*) 字节开始超过allocated_mem,所以“额外空间”至少是sizeof(void*) 字节。此外,aligned_memvoid* 正确对齐,因此我们可以在它之前存储一个void*。在第 3 点,内存块看起来像这样

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

对于aligned_free,它只是读取存储在那里的指针并将其传递给::operator delete

【讨论】:

虽然我不知道你为什么要在 Windows 上已经存在这两个函数时这样做。 @user1235183 aligned_alloc::operator new 返回的指针隐藏在其返回值指向的内存块之前。然后aligned_free 只需读取该指针并将其传递给::operator delete

以上是关于在 MS Visual Studio 2013 中,我可以使用啥来代替 std::aligned_alloc?的主要内容,如果未能解决你的问题,请参考以下文章

在 Visual Studio 2013 中使用 MS Access (C#) 生成发票

在 MS Visual Studio 2013 中,我可以使用啥来代替 std::aligned_alloc?

Visual Studio 2013 错误 MS8020 Build tools v140 找不到

Visual Studio 2013 与 MS SQL Server 2014 不兼容

MS Visual Studio 2013 MFC 应用程序:为消息/输出服务创建文本框

如何在 MFC 中支持多种文档类型,例如 MS Office 应用程序或 Visual Studio