c++中申请首地址对齐内存空间的几种方法

aligned_alloc

https://en.cppreference.com/w/c/memory/aligned_alloc

1
2
3
4
#include <cstdlib>

double *aligned_ptr = static_cast<double *>(std::aligned_alloc(256, 4096 * sizeof(double))); // 申请一片首地址256字节对齐的,大小为4096个double的内存
free(aligned_ptr)

vector+自定义allocator

自定义可设置AlignSize的allocator,很奇怪,deallocator里用delete[] 会报free() invalid pointer的错,无奈之下用malloc和free了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <iostream>

template <typename T, size_t AlignSize>
class AlignedAllocator
{
private:

void *adjust(void *p)
{
return reinterpret_cast<void *>((reinterpret_cast<size_t>(p) + sizeof(T *)) | (AlignSize - 1) + 1);
}

public:

using value_type = T;

template <typename U>
struct rebind
{
using other = AlignedAllocator<U, AlignSize>;
};

T *allocate(size_t n)
{
const size_t allocateSize = n * sizeof(T) + AlignSize + sizeof(T *);
__u_char *rawPtr = reinterpret_cast<__u_char *>(malloc(allocateSize));
T *alignedPtr = reinterpret_cast<T *>(adjust(rawPtr));
reinterpret_cast<T **>(alignedPtr)[-1] = reinterpret_cast<T *>(rawPtr);
return alignedPtr;
}

void deallocate(T *p)
{
free(reinterpret_cast<T **>(p)[-1]);
}

void deallocate(T *p, size_t n)
{
free(reinterpret_cast<T **>(p)[-1]);
}

void construct(T *p, const T &val)
{
new (p) T(val);
}

void destroy(T *p)
{
p->~T();
}
};

class Test
{
public:
Test()
{
std::cout << "Test construct.\n";
}

Test(const Test &other)
{
std::cout << "Test copy construct.\n";
}

~Test()
{
std::cout << "Test destroy.\n";
}
};

template <typename T, size_t AlignSize>
using AlignedVector = std::vector<T, AlignedAllocator<T, AlignSize>>;

int main(int argc, char *argv[])
{
constexpr size_t CacheLineSizeByte = 128;
AlignedVector<Test, CacheLineSizeByte> testVector(10);

return 0;
}