用户代码可以安全地使用结构填充吗?
Posted
技术标签:
【中文标题】用户代码可以安全地使用结构填充吗?【英文标题】:Can the struct padding be safely used by the user code? 【发布时间】:2011-01-02 01:37:23 【问题描述】:假设我有如下结构:
struct Struct
char Char;
int Int;
;
并且sizeof( int )
大于一并且编译器为Char
成员变量添加填充 - 编译器生成的代码是否允许更改填充字节的值?
我的意思是,如果我使用指针算法并将一些数据写入 Char
成员变量周围的填充字节,然后再进行 variable.Char =
赋值,编译器生成的代码可能还会覆盖一些填充字节?
【问题讨论】:
@nobugz,我认为这是一个有效的问题。在设置值之前您已将结构设置为 0 的图像,然后您可以稍后使用 memcmp 比较两个结构,但前提是编译器不接触填充字节。 不要乱用填充,memset
或 memcpy
使用类和结构。 更安全和更健壮的方法是实现读取和写入打包缓冲区的方法(例如unsigned char[]
)。保险值得额外的可执行空间和时间。
@Thomas Matthews,我想你误解了我的意思。我在谈论比较两个结构,请参阅***.com/questions/141720/…
如果您关心字节对齐,大多数编译器允许您显式声明它。例如,在 VS 中,您可以使用 #pragma pack(1) 告诉编译器完全按照声明的方式打包您的结构,而无需额外填充。在这种情况下,sizeof(Struct) 将恰好是 sizeof(char)+sizeof(int),仅此而已。我见过使用这种机制的唯一有效用途是套接字编程,但我确信还有其他原因。
【参考方案1】:
以下句子错误:不,它不会覆盖填充字节。但使用它可能不是一个好习惯。如果需要,可以在里面添加成员变量。
我根据 cmets 进行了研究,表明(正确)我很愚蠢:
C 标准有一个“附件 J”,其中包含 J.1 未指定行为部分。它说,“在结构或联合中存储值时填充字节的值”。这意味着编译器可以生成它想要将数据写入结构的任何指令,这可能允许它覆盖成员之后的填充。
【讨论】:
没有什么可以阻止编译器覆盖填充。 过失。你是对的。没有什么可以阻止它。 C 标准的附件 J 将“结构中填充字节的值”列为未指定。【参考方案2】:你当然可以在那里写一些东西,memset
-ing 一个这样的结构的实例就可以了。但是,这样做并不安全,也不是一个好主意。有一天,另一个开发人员在某处放置#pragma
或在结构声明中添加一个成员,您的代码将以许多奇怪而奇特的方式爆炸,这可能需要相当长的时间来调试。
【讨论】:
【参考方案3】:如果编译器足够聪明,可以使用单词 write 来保存 char 会怎样?您精心保存的数据将会丢失。 ;-)
【讨论】:
对,我认为这就是问题所在。编译器是否允许这样做? 编译器显然被允许这样做。我更新了我的不正确答案以表明尽可能多的内容,并对此表示赞同。【参考方案4】:这样做的唯一原因是某个插件恶意欺骗主机应用程序存储额外数据。
但不要这样做,因为在未来的某个时候它会坏掉,这对所有相关人员来说都会是一件非常头疼的事情。
【讨论】:
以上是关于用户代码可以安全地使用结构填充吗?的主要内容,如果未能解决你的问题,请参考以下文章