Fre*_*ler 12 c++ memory-alignment language-lawyer c++20 c++-coroutine
编辑:感谢大家的回答和回复。Language Lawyer 的答案在技术上是正确的,因此被接受,但 Human-Compiler 的答案是唯一符合赏金标准(获得 2+ 分)的答案,或者对问题的特定主题进行了充分阐述。
将对象b
置于协程状态是否定义了行为(例如,将其作为参数,或将其保留在暂停点上),在哪里alignof(b) > __STDCPP_DEFAULT_NEW_ALIGNMENT__
?
例子:
inline constexpr size_t large_alignment =
__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2;
struct alignas(large_alignment) behemoth {
void attack();
unsigned char data[large_alignment];
};
task<void> invade(task_queue &q) {
behemoth b{};
co_await submit_to(q);
b.attack();
}
Run Code Online (Sandbox Code Playgroud)
当调用协程时,协程状态的堆内存通过operator new
.
此调用operator new
可能采用以下形式之一:
无论调用采用哪种形式,请注意它不使用接受 a 的重载std::align_val_t
,这是分配必须对齐多于 的内存所必需的__STDCPP_DEFAULT_NEW_ALIGNMENT__
。因此,如果__STDCPP_DEFAULT_NEW_ALIGNMENT__
必须将对齐大于 的对象保存在协程状态中,则应该无法保证该对象最终会在内存中正确对齐。
async f(): Assertion `reinterpret_cast<uintptr_t>(&b) % 32ull == 0' failed.
Run Code Online (Sandbox Code Playgroud)
所以它绝对不能在 GCC 主干 ( 11.0.1 20210307
) 上工作。替换32
为16
(等于__STDCPP_DEFAULT_NEW_ALIGNMENT__
)消除了这个断言失败。
Godbolt.org 无法运行 Windows 二进制文件,但断言也在我的计算机上使用 MSVC 触发。
是否支持任何扩展对齐以及支持它们的上下文是由实现定义的。
所以答案是:实现定义的。这句话的第二部分听起来像是一个实现可能支持在普通函数中创建过度对齐类型的对象,但在协程中不支持。
如果实现不支持对特定上下文中的特定扩展对齐的请求,则该程序是格式错误的。
当不支持扩展对齐时不发出诊断消息的实现是不合格的。
归档时间: |
|
查看次数: |
334 次 |
最近记录: |