不应在模块之间传递非标准布局类型的对象
2.8 ID_ABIConflict
非标准布局类型的运行时特性依赖编译器的具体实现,在不同编译器生成的模块间传递这种类型的对象会导致运行时错误。
“标准布局(standard-layout)”类型的主要特点:
- 没有虚函数也没有虚基类
- 所有非静态数据成员均具有相同的访问权限
- 所有非静态数据成员和位域都在同一个类中声明
- 不存在相同类型的基类对象
- 没有非标准布局的基类
- 没有非标准布局和引用类型的非静态数据成员
除非模块均由同一编译器的同一版本生成,否则不具备上述特点的对象不应在模块之间传递。
示例:
// a.dll
class A {
....
public:
virtual void foo(); // Non standard-layout
};
void bar(A&);
// b.exe
int main() {
A a;
bar(a); // Non-compliant
}
设例中 a.dll 和 b.exe 由不同的编译器生成,b.exe 中定义的 a 对象被传递给了 a.dll 中定义的接口,由于存在虚函数,不同的编译器对 a 对象的内存布局会有不同的解读,从而造成冲突。
依据
ISO/IEC 14882:2011 9(7)
ISO/IEC 14882:2017 12(7)