更改派生类型的对齐
Changing alignment in derived type
说您有这两种类型:
struct alignas(8) Base { double a; double b; }
struct alignas(16) Derived : public Base {}
和这些功能:
void Foo(Base b)
void Bar(Base* start, Base* end)
打电话
是合法的Foo(someDerived)
Bar(someDerivedArray, someDerivedArray + arrayLength)
在所有情况下?这是否取决于Base
的内容和特定的对齐限制?我绝对可以看到,如果derived
是32位对齐的,因为someDerivedArray
和Bar
的元素之间会有一个间隙,但我不确定。
xy说明:我们使用的是GPGPU库推力,其复杂类型在设备代码和主机代码之间的比对不一致;我们正在尝试弄清楚如何解决这个问题。一种选择是定义我们自己的复杂类型,该类型从thrust::complex
衍生而来,但使用相同的对齐方式并使用它,但是当然,各种推力功能都会期望thrust::complex
,因此我们将切入或施放到较少分配的类型中。
在Base*
上执行指针算术,如果指针实际上指向Derived
对象,则总是UB。对齐是无关紧要的。如果 Base
和 Derived
具有相同的 size ,那么这似乎是有效的,但是它仍然是ub。
将指针传递到Derived
对象到占用Base*
的函数,并且执行指针算术通常很好,请注意,如果该函数将在指针上执行delete
,则那么Base
必须具有虚拟驱动器。同样,对齐不相关。
增加Derived
对齐的原因是没有区别的,即Base
子对象仍然被迫根据Base
的对齐方式对齐。(这就是为什么一般而言,您可以增加相对于基类的派生类的对齐,但不能减小。)因此,当Derived*
转换为Base*
时,您仍然会得到有效的指针值:它指向一个Base
对象和该对象正确对齐。(实际上,没有一个对象没有适当对齐的对象。任何创建此类对象的尝试都会引起UB。)
因此,只要Foo
不尝试delete
指针,Foo(someDerived)
通常就可以了,而Bar(someDerivedArray, someDerivedArray + arrayLength)
则不会。
alignas
仅适用于基础和派生;他们不适用于其成员:a
和b
。
所以没有问题。
#include <iostream>
using namespace std;
struct A
{
int x, y, z, w;
};
struct alignas(64) B
{
alignas(64) int x;
alignas(64) float y, z, w;
};
struct alignas(64) C : public A
{
};
int main()
{
A a;
B b;
C c;
cout << size_t((char*)(void*)&(a.y)-(char*)(void*)&(a.x)) << endl;
cout << size_t((char*)(void*)&(b.y)-(char*)(void*)&(b.x)) << endl;
cout << size_t((char*)(void*)&(c.y)-(char*)(void*)&(c.x)) << endl;
return 0;
}
它返回
4
64
4
编辑:如果您不相信我,请自己运行代码。我不确定为什么有人会认为alignas
会与班级的每个成员强制对齐。alignas
的定义指出,它适用于课程本身(只有类的对齐受其成员的对齐的影响,而不是受班级影响的成员)。
编辑2 :关于推力 - 如果设备和主机决定类中的不同对齐方式,那么这是需要同步的不同编译器一致性的错误。您可以将错误提交给Nvidia,因为这是他们的问题。
如何解决此类问题?这是一个复杂的问题...祝你好运。
- 运行时错误:引用绑定到类型"int"的未对齐地址0xbebebebebebebec6,这需要 4 个字节对齐 (stl_vector.h)
- 具有调整对齐方式的类型定义
- 外部基础类型未按请求对齐时的atomic_ref
- 如何分配适合容纳 T 类型对象的缓冲区(可能过度对齐、可能有运算符 new 等)
- 对象地址是否保证是其类型对齐的倍数
- 对齐C++字符串类型问题 std::字符串到 TStr
- 数据对齐:限制内存地址为数据类型大小倍数的原因
- 与 std::aligned_storage 过度对齐的类型
- 在英特尔上自然对齐的POD类型的保证原子操作
- 更改派生类型的对齐
- 幻影类型是否与原始类型具有相同的对齐方式
- 对齐说明符:在类型 / 上 成员数据
- 如何检查该类型的类型指针是正确对齐的
- 类型是否可以具有除'n-byte alignment'以外的对齐要求
- 与包含的类型相比,数组在C++中的对齐方式如何?2.
- 新字符是否实际上保证类类型的对齐内存
- 我不明白在下面的代码中将 char buffer[] 与 X 类型的对象对齐的原因
- 标准是否要求自动存储中的对象对任何类型都具有正确的对齐方式(例如malloc)
- 基本类型和结构的对齐,内部只有这个基本类型
- 抛出对齐类型时出现 Clang 运行时错误.编译器错误