alignas、alignof、sizeof实现内存对齐分配
# alignas、alignof、
sizeof实现内存对齐分配
# 什么时候需要 posix_memalign
malloc 在32位上分配8字节对齐,在64位上16字节对齐。 但是当需要更多更大的对齐方式时就用到了,比如4K-aligned
对一个类型为T的对象数组分配内存,且满足其内存对齐要求:
// - 分配大小为sizeof(T) * n
// - 对齐方式为alignof(T)
T *p;
posix_memalign(reinterpret_cast<void **>(&p), alignof(T), sizeof(T) * n);
// 或者:
typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
1
2
3
4
5
6
7
2
3
4
5
6
7
注意typename指示一个类型名,而非定义一个类型,以下声明了一个T::iterator类型的变量itr,其中T是一个模板实例化时才知道的类:
typename T::iterator itr;
1
如果没有typename指示,T::iterator会被认为是T的静态变量,而不是类型名。
typename关键字不会定义一个类型,如果你想定义一个新类型的话,你必须这样:
typedef typename T::iterator ITR;
1
下面是一个AlignedAllocator的示例
#if defined(__cpp_aligned_new)
template <typename T> using AlignedAllocator = std::allocator<T>;
#else
template <typename T> struct AlignedAllocator {
using value_type = T;
T *allocate(std::size_t n) {
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T)) {
throw std::bad_array_new_length();
}
#ifdef _WIN32
auto *p = static_cast<T *>(_aligned_malloc(sizeof(T) * n, alignof(T)));
if (p == nullptr) {
throw std::bad_alloc();
}
#else
T *p;
if (posix_memalign(reinterpret_cast<void **>(&p), alignof(T),
sizeof(T) * n) != 0) {
throw std::bad_alloc();
}
#endif
return p;
}
void deallocate(T *p, std::size_t) {
#ifdef _WIN32
_aligned_free(p);
#else
free(p);
#endif
}
};
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
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
# 地址对齐
优点:提高性能 假设计算机的字大小为4个字节(32位),CPU每次只能对4的倍数内存地址进行读取, 如果一个4字节的变量其地址是4的倍数,那么cpu一次就可以读出来。如果不是4的倍数,那就要读两次。
默认结构体的对齐方式: https://blog.csdn.net/u011404495/article/details/54837797 (opens new window)
假设首变量地址为0,其内部成员的地址是自身对齐长度的整数倍。
禁用对齐
struct pkg_hdr { uint32_t len; uint32_t code; uint8_t type; } __attribute__((packed));
1
2
3
4
5
# alignas用法
#include <string>
#include <iostream>
using namespace std;
struct struct_Test1 { char c; int i; double d; };
struct struct_Test2 { char c; double d; int i; };
struct alignas(16) struct_a16
{ char c; int i; double d; //inner same as test1 };
struct alignas(32) struct_a32
{ char c; int i; double d; //inner same as test1 };
int main()
{
struct_Test1 test1;
struct_Test2 test2;
struct_a16 a16;
struct_a32 a32;
cout << "char alignment:" << alignof(char) << endl; //1
cout << "int alignment:" << alignof(int) << endl; //4
cout << "double alignment:" << alignof(double) << endl; //8
cout << "test1 size:" << sizeof(test1) << endl; //16
cout << "test2 size:" << sizeof(test2) << endl; //24
cout << "test1 alignment:" << alignof(test1) << endl; //8
cout << "test2 alignment:" << alignof(test2) << endl; //8
cout << "a16 alignment:" << alignof(a16) << endl; //16
cout << "a32 alignment:" << alignof(a32) << endl; //32
cout << "a16 size:" << sizeof(a16) << endl; //16
cout << "a32 size:" << sizeof(a32) << endl; //32
system("pause");
return 0;
}
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
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
编辑 (opens new window)
上次更新: 2023/05/07, 17:27:54