在堆上分配std::aligned_storage<2, 4096>::type
时,我总是得到一个偏移16个字节的指针(在x64上;在x86上,它偏移8个字节)。换句话说,这个:
#include <iostream>
#include <cstddef>
int main() {
typedef std::aligned_storage<2, 4096>::type MemPage;
MemPage* p_mp = new MemPage;
std::cout << (void*)p_mp << std::endl;
return 0;
}
给我(例如)
0x72f010
虽然我希望所有后三位数都为零。在堆栈上分配std::aligned_storage<>::type
时,一切都按预期工作。
我在ubuntu 14.04上使用gcc-4.8.2 x86_64。
答案 0 :(得分:9)
目前尚不清楚对齐要求如何转换为使用new
分配的存储空间。该标准在[expr.new]中保留了
实现定义是否支持过度对齐类型 (3.11)。
[basic.align] / 3:
扩展对齐由大于的对齐表示
alignof(std::max_align_t)
。它是否是实现定义的 支持扩展对齐及其所在的上下文 支持(7.6.2)。 具有扩展对齐要求的类型 是过度对齐类型 。
GCC可能不支持过度对齐的类型,并且“不支持”可能(而不是编译器错误)导致分配函数仅返回与最严格的基本对齐对齐的存储:sizeof(std::max_align_t)
。如果后者的值在您的机器上为16,则可以解释该地址是16的倍数。
另请注意,尽管运行时分配函数将具有最大支持对齐,但operator new
基本上不能将所需的对齐考虑在内,因为它没有可以获取相应值的参数并将其传递给运行时环境分配功能。这个问题是已知的,并且是EWG-issue。
Fun-fact:上面的代码正在调用UB。考虑[meta.trans.ptr]中的表,其中列出了aligned_storage
第二个模板参数的要求:
Align
对于某些类型alignof(T)
或者T
应该等于T
默认对准
如果类型4096
没有new
的对齐方式,则模板参数的要求不合适。什么类型的对齐 2 12 ?
然而,这对问题的本质并不重要。我们可以将{{1}}与自己的typedef一起使用。