分配32字节对齐内存的分配器
Allocator that allocates 32-byte aligned memory
下面的代码定义了一个自定义分配器,用于分配32字节对齐的内存。
我使用Visual Studio 2010编译了代码。代码在发布模式下编译良好。在调试模式下,我得到了一个编译错误,见下文,我不理解。代码出了什么问题?
#include <memory>
#include <vector>
inline void* aligned_malloc(size_t n)
{
if(n == 0) return nullptr;
char* p = (char*)malloc(n + 32);
if(p == nullptr) return nullptr;
size_t offset = 32 - (size_t)p % 32;
p += offset;
*(p - 1) = (char)offset;
return p;
}
inline void aligned_free(void* p)
{
if(p == nullptr) return;
char offset = *((char*)p - 1);
free((char*)p - offset);
}
template<class T>
class AlignedAllocator {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
T* address(T& x) const { return &x; }
const T* address(const T& x) const { return &x; }
size_t max_size() const { return (size_t)(-1) / sizeof(T); }
T* allocate(size_t n, const T* = nullptr)
{
T* p = (T*)aligned_malloc(n * sizeof(T));
if(!p) throw std::bad_alloc();
return p;
}
void deallocate(pointer p, size_type) { aligned_free(p); }
void construct(T* p, const T& x) { new(p) T(x); }
void destroy(T* p) { p->~T(); }
template<class U> struct rebind { typedef AlignedAllocator<U> other; };
};
std::vector<int, AlignedAllocator<int>> v;
调试模式下的编译错误:
c:program files (x86)microsoft visual studio 10.0vcincludevector(441): error C2440: 'initializing' : cannot convert from 'AlignedAllocator<T>' to 'AlignedAllocator<T>'
with
[
T=int
]
and
[
T=std::_Container_proxy
]
No constructor could take the source type, or constructor overload resolution was ambiguous
c:program files (x86)microsoft visual studio 10.0vcincludevector(437) : while compiling class template member function 'std::_Vector_val<_Ty,_Alloc>::_Vector_val(_Alloc)'
with
[
_Ty=int,
_Alloc=AlignedAllocator<int>
]
c:program files (x86)microsoft visual studio 10.0vcincludevector(481) : see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled
with
[
_Ty=int,
_Alloc=AlignedAllocator<int>
]
c:usersradedesktop 5higg boson repositorytmptmp.cpp(52) : see reference to class template instantiation 'std::vector<_Ty,_Ax>' being compiled
with
[
_Ty=int,
_Ax=AlignedAllocator<int>
]
分配器要求,除其他外,要求给定一个分配器类型X
、任何类型U
和
using Y = typename X::template rebind<U>::other;
您能够从类型为X
的对象构造CCD_ 3。(应用于代码的缺点是,对于任意类型的Foo
和Bar
,您必须能够从AlignedAllocator<Bar>
构造AlignedAllocator<Foo>
。)您的分配器不能满足这一要求。在调试模式下,MSVC标准库会重新绑定分配器,以维护一些额外的内部数据,用于调试目的,而在发布模式下,它不会这样做,这就是为什么你只会在调试模式中看到编译器抱怨的原因。
修复很简单-只需添加必要的构造函数:
AlignedAllocator() { }
template<class U> AlignedAllocator(const AlignedAllocator<U> &) { }
这里是代码的工作版本。它结合了我的问题、T.C.的答案和一些额外的修复程序中的代码。我把它贴在这里,以防有人发现它有用。
该代码已在MSVS2008和MSVS2010中进行了测试。它是用C++98编写的。为了使其符合C++11分配器的要求,可能需要进行一些更改。
#include <cstdlib>
#include <new>
inline void* alignedMalloc(size_t n)
{
char* p = (char*)std::malloc(n + 32);
if(!p) return 0;
size_t offset = 32 - (size_t)p % 32;
p += offset;
*(p - 1) = (char)offset;
return p;
}
inline void alignedFree(void* p)
{
if(!p) return;
char offset = *((char*)p - 1);
std::free((char*)p - offset);
}
template<class T>
class AlignedAllocator {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
AlignedAllocator() {}
template<class U> AlignedAllocator(const AlignedAllocator<U>&) {}
T* address(T& x) const { return &x; }
const T* address(const T& x) const { return &x; }
size_t max_size() const { return (size_t)(-1) / sizeof(T); }
T* allocate(size_t n, const T* = 0)
{
T* p = (T*)alignedMalloc(n * sizeof(T));
if(!p) throw std::bad_alloc();
return p;
}
void deallocate(T* p, size_t) { alignedFree(p); }
void construct(T* p, const T& x) { new(p) T(x); }
void destroy(T* p) { (void)p; p->~T(); } // (void)p silences spurious MSVS 2010 compiler warning
template<class U> struct rebind { typedef AlignedAllocator<U> other; };
};
template <class T>
bool operator==(const AlignedAllocator<T>&, const AlignedAllocator<T>&) { return true; }
template <class T>
bool operator!=(const AlignedAllocator<T>&, const AlignedAllocator<T>&) { return false; }
相关文章:
- C++:矢量分配器行为、内存分配和智能指针
- 是否可以使用分配器对象来释放另一个分配器分配的内存?
- 基于浅树的数据结构的内存分配器,用于频繁分配和解除分配
- shared_ptr的删除程序是否存储在自定义分配器分配的内存中?
- STD分配器是否会在堆上动态分配内存?它可以安全地删除内存吗?
- std::unordered_map 在共享内存中使用 boost:::进程间分配器 - 缺点?
- 支持 CUDA 统一内存的系统分配器的操作系统版本
- 分配分配器为多态对象分配内存
- 如何通过分配器分配内存[10] [10]
- 使用 AMD 的 Vulkan 内存分配器时出现链接器错误 (LNK2005)
- 自定义内存分配器示例(需要一些说明)
- 跨共享/静态库集成C++自定义内存分配器
- 带有realloc的自定义池内存分配器
- C++ 分配器在内存不足时使应用程序崩溃
- 复制有状态分配器:标准库分配器语义和内部内存
- 正在重写MSVC++中的内存分配器
- 将运算符new和运算符delete与自定义内存池/分配器一起使用
- 进程间共享内存的非Boost STL分配器
- 如何使用 CUDA 推力执行策略覆盖推力的低级设备内存分配器
- 如何测试分配器是否使用std::allocate进行内存分配