我知道sizeof空结构是1,但当与模板结合使用时,这可能会导致类的大小可能会产生误导。
例如,在下面的代码中,假设我正在编码一个二进制协议,其中有某些重要的字段,后面跟着一个可选的结构。
创建消息后,我们使用sizeof( message )执行memcpy,但我们总共得到了2个字节,并尝试发送2个字节,尽管实际只有1个字节的消息。这是危险的,并导致了一些地址消毒器问题。
我已经研究了空基优化,但只有当可选字段在开头时才会起作用。即使我们在这个特定的实例中不使用sizeof,在其他通用代码中也通常使用sizeof来处理这样的消息。
struct EmptyClass{
// empty class is 1 byte
};
struct NonEmptyClass{
uint32_t j = 1; // non-empty class is 4 bytes
};
#pragma pack(push, 1) // exact fit - no padding
template <typename A>
struct Message{
bool i = true; // example of an important field of 1 byte
A a; // 1 byte if empty, 4 bytes if full
};
#pragma pack(pop)
int main() {
Message<NonEmptyClass> a;
std::cout << "Size of nonEmpty a: " << sizeof(a) << std::endl; // 5
Message<EmptyClass> b;
std::cout << "Size of Empty b: " << sizeof(b) << std::endl; // 2
// memcpy b results in address-sanitizer issues, and likely garbage values for the second byte
return 0;
}
一般来说,这是否意味着解决这类问题的唯一方法是拥有一个自定义(编译时)大小操作符,因为sizeof是不可覆盖的?
使用sizeof( Type )来记录所述类型是否安全?
发布于 2019-07-16 03:12:05
的大小(类型)是否可以安全地用于记忆所述类型?
对于所有简单的可复制类型,都是这样的。更具体地说,复制填充字节是安全的。
但是一个类的表示在不同的系统中不一定是相同的。类不是表示二进制通信协议结构的理想方式。
请注意,如果将示例扩展为实际使用a
或b
,则在示例中存在潜在问题。a.a
和a.b
是未初始化的,因此读取它们的值的行为是未定义的。memcpy
本身实际上是安全的,但将复制的数据解释为EmptyClass
或NonEmptyClass
就不安全了。
https://stackoverflow.com/questions/57045616
复制相似问题