13

我很难找到有关 GCC 的对齐新警告和 gcc -faligned-new 选项的更多信息。在 gcc 7.2.0 上编译(没有 --std=c++17)并尝试定义一个对齐的结构,例如:

struct alignas(64) Foo { int x; }

只是做一个简单的旧:

Foo * f = new Foo();

给我以下警告和建议:

 alignas.cpp:36:25: warning: ‘new’ of type ‘Foo’ with extended alignment 64 [-Waligned-new=]
 Foo * f = new Foo();
                     ^
 alignas.cpp:36:25: note: uses ‘void* operator new(long unsigned int)’, which does not have an alignment parameter
 alignas.cpp:36:25: note: use ‘-faligned-new’ to enable C++17 over-aligned new support

我知道默认情况下new只会返回对齐到alignof( std::max_align_t )(对我来说是 16)的内存,但我不清楚的是,如果我通过 -faligned-new,gcc 现在会new代表我强制执行正确的新对齐吗?

不幸的是,这方面的 gcc 文档非常缺乏。

4

1 回答 1

10

来自gcc 的手册

-faligned-new
启用对new需要比void* ::operator new(std::size_t)提供更多对齐的类型的 C++17 的支持。诸如 -faligned-new=32 之类的数字参数可用于指定该函数提供多少对齐(以字节为单位),但很少有用户需要覆盖默认的alignof(std::max_align_t).

这意味着 -faligned-new 只是使 P0035R4 中添加的对齐新功能可用,而无需完全启用 C++17 支持。

C++ 标准中的相关位:
来自 [cpp.predefined]:

__STDCPP_DEFAULT_NEW_ALIGNMENT__
一个整数类型的文字,std::size_t其值是调用operator new(std::size_t)or保证的对齐方式operator new[](std::size_t)。[注意:更大的对齐将被传递给operator new(std::size_t, std::align_val_t),等等(8.3.4)。——尾注]

来自 [basic.align/3]:

扩展的对齐由大于的对齐表示__STDCPP_DEFAULT_NEW_ALIGNMENT__

来自 [expr.new/14]:

重载解析是在通过组装参数列表创建的函数调用上执行的。第一个参数是请求的空间量,类型为std::size_t。如果分配对象的类型具有新扩展对齐,则下一个参数是类型的对齐,并且具有 type std::align_val_t


因此,在您使用 C++17 或 -faligned-new 的情况下,由于Foo具有新扩展对齐Foo* f = new Foo();将调用void* operator new(size_t, align_val_t)分配内存并返回指向Foo在 64 字节边界上正确对齐的对象的指针。根据早期的标准,情况并非如此。

于 2018-03-19T23:42:03.187 回答