联合内存分配不足
Underallocating memory for a union
鉴于此声明:
struct s1 {
int type;
union u1 {
char c;
int i[10000];
} u;
} s;
我想知道我们是否可以为结构分配比 sizeof(struct s1) 建议更少的内存:
struct s1 * s_char = malloc(sizeof(int)+sizeof(char));
一方面,这似乎很直观:如果知道 s/he 永远不会超过 char s_char.u.c
,那么分配整个 sizeof(struct s1) 看起来就是一个很大的浪费。
另一方面,我宁愿理解 C11 标准反对这一点 - 但它从未被阐明。我发现可以理解为反对这一点的两段是:
- if 该结构以某种方式假设其完整大小已被分配,这为未定义行为打开了大门:可以在 s_char 之后分配一个新对象但是仍在结构假定的 "real" sizeof(struct s1) 字节内,然后将触发 C11 标准附件 J.2 的第 54 项:UB if
An object is assigned to an inexactly overlapping object or to an
exactly overlapping object with incompatible type (6.5.16.1).
- 6.2.6.1 第 7 段:
When a value is stored in a member of an object of union type, the
bytes of the object representation that do not correspond to that
member but do correspond to other members take unspecified values.
但这也可以理解为标准拒绝处理这些值发生的情况,或者说这些值实际上可以预期任意改变。
总而言之,有一种直觉 "but we're only using 5 bytes!" vs 语言律师 谨慎 - 不是 证明 .我的问题是:有任何一方有更多证据吗?更具体地说:为联合或任何其他数据结构分配不足的内存是否可以?
再说一次:直觉是带来问题的原因,我不想再这样了。我正在寻找基于可靠事实的推理,例如 C11 标准 and/or 编译器信息。此外,我已经知道执行此操作的标准方法是用联合结构替换具有公共初始序列的联合结构,尽管这也是 ... 。但这在这里是切线的。
看起来 GCC 维护者认为联合内存分配不足会导致 UB,如 this bug report 中所见(有点切线)。没有基于标准的解释,但这仍然意味着不能期望编译器支持它,因此进一步查看没有意义。
为了完整起见,this Defect Report against a rule of the CERT C Secure Coding Rules 显示此文本:
A call to a standard memory allocation function taking a size integer argument n and presumed to be intended for type T * shall be diagnosed when n < sizeof(T).
负责 C 标准的 WG14 小组也参与了 CSCR。这是我最接近于相对基于标准的东西。
您似乎在寻找超出 C 语言范围的答案,这让您自己感到困惑。正如@M.M 所说,这个问题并不特定于工会。如果您没有为一个对象分配足够的内存,并且您在分配的内存之外写入该对象的一部分,那么如果事情后来变得糟糕,请不要感到惊讶。
C 语言允许您定义指向任何已知类型的指针,甚至是仅 "known" 属性 是其名称的不完整类型。当您为该指针赋值时,由程序员来确保提供的值有效。 C 会将指向的区域视为指针类型的对象。这对你来说很方便,可以帮助你浏览记忆。
请记住 "where the memory comes from" 超出了语言的范围。它可能来自 malloc,但也可能来自 sbrk(2) 或 mmap(2)。或者它可以只是一个常量,就像原始 IBM PC 中的视频 RAM 缓冲区一样。如果你错误地描述了所指的东西,你就不能指望编译器来拯救你。
鉴于此声明:
struct s1 {
int type;
union u1 {
char c;
int i[10000];
} u;
} s;
我想知道我们是否可以为结构分配比 sizeof(struct s1) 建议更少的内存:
struct s1 * s_char = malloc(sizeof(int)+sizeof(char));
一方面,这似乎很直观:如果知道 s/he 永远不会超过 char s_char.u.c
,那么分配整个 sizeof(struct s1) 看起来就是一个很大的浪费。
另一方面,我宁愿理解 C11 标准反对这一点 - 但它从未被阐明。我发现可以理解为反对这一点的两段是:
- if 该结构以某种方式假设其完整大小已被分配,这为未定义行为打开了大门:可以在 s_char 之后分配一个新对象但是仍在结构假定的 "real" sizeof(struct s1) 字节内,然后将触发 C11 标准附件 J.2 的第 54 项:UB if
An object is assigned to an inexactly overlapping object or to an exactly overlapping object with incompatible type (6.5.16.1).
- 6.2.6.1 第 7 段:
When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.
但这也可以理解为标准拒绝处理这些值发生的情况,或者说这些值实际上可以预期任意改变。
总而言之,有一种直觉 "but we're only using 5 bytes!" vs 语言律师 谨慎 - 不是 证明 .我的问题是:有任何一方有更多证据吗?更具体地说:为联合或任何其他数据结构分配不足的内存是否可以?
再说一次:直觉是带来问题的原因,我不想再这样了。我正在寻找基于可靠事实的推理,例如 C11 标准 and/or 编译器信息。此外,我已经知道执行此操作的标准方法是用联合结构替换具有公共初始序列的联合结构,尽管这也是
看起来 GCC 维护者认为联合内存分配不足会导致 UB,如 this bug report 中所见(有点切线)。没有基于标准的解释,但这仍然意味着不能期望编译器支持它,因此进一步查看没有意义。
为了完整起见,this Defect Report against a rule of the CERT C Secure Coding Rules 显示此文本:
A call to a standard memory allocation function taking a size integer argument n and presumed to be intended for type T * shall be diagnosed when n < sizeof(T).
负责 C 标准的 WG14 小组也参与了 CSCR。这是我最接近于相对基于标准的东西。
您似乎在寻找超出 C 语言范围的答案,这让您自己感到困惑。正如@M.M 所说,这个问题并不特定于工会。如果您没有为一个对象分配足够的内存,并且您在分配的内存之外写入该对象的一部分,那么如果事情后来变得糟糕,请不要感到惊讶。
C 语言允许您定义指向任何已知类型的指针,甚至是仅 "known" 属性 是其名称的不完整类型。当您为该指针赋值时,由程序员来确保提供的值有效。 C 会将指向的区域视为指针类型的对象。这对你来说很方便,可以帮助你浏览记忆。
请记住 "where the memory comes from" 超出了语言的范围。它可能来自 malloc,但也可能来自 sbrk(2) 或 mmap(2)。或者它可以只是一个常量,就像原始 IBM PC 中的视频 RAM 缓冲区一样。如果你错误地描述了所指的东西,你就不能指望编译器来拯救你。