c - union 内存分配不足

标签 c language-lawyer dynamic-memory-allocation undefined-behavior unions

鉴于此声明:

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)); 

一方面,这似乎很直观:如果一个人知道她/他永远不会超过 char s_char.u.c,那么分配整个 sizeof(struct s1) 看起来就是一个很大的浪费。

另一方面,我宁愿理解 C11 标准反对这一点——但它从未被阐明。我发现可以理解为反对这一点的两段是:

  • 如果结构以某种方式假定其完整大小已被分配,这为未定义行为打开了大门:可以在 s_char 之后分配一个新对象,但仍在“真实”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.

但这也可以理解为标准拒绝处理这些值发生的情况,或者说这些值实际上可以预期任意改变。

总之,直觉是“但我们只使用了 5 个字节!” vs 语言律师警告 - 不是证据。我的问题是:有任何一方有更多证据吗?更具体地说:为 union 或任何其他数据结构分配不足的内存是否可行?

再说一次:直觉是带来问题的原因,我不想要更多。我正在寻找基于可靠事实的推理,例如 C11 标准和/或编译器信息。此外,我已经知道执行此操作的标准方法是用 union 结构替换具有公共(public)初始序列的 union 结构,尽管这也是 not without risks ……但这在这里是切线的。

最佳答案

您似乎在寻找超出 C 语言范围的答案,这让您自己感到困惑。正如@M.M 所说,这个问题并不特定于 union 。如果您没有为一个对象分配足够的内存,并且您在分配的内存之外写入该对象的一部分,那么如果事情后来变得糟糕,请不要感到惊讶。

C 语言允许您定义指向任何已知类型的指针,甚至是指向其唯一“已知”属性是其名称的不完整类型。当您为该指针赋值时,由程序员来确保提供的值有效。 C 会将指向的区域视为指针类型的对象。这对你来说很方便,可以帮助你浏览内存。

请记住,“内存从何而来”超出了语言的范围。它可能来自 malloc,但也可能来自 sbrk(2) 或 mmap(2)。或者它可以只是一个常量,就像原始 IBM PC 中的视频 RAM 缓冲区一样。如果你错误地描述了所指的东西,你就不能指望编译器来拯救你。

关于c - union 内存分配不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40570426/

相关文章:

c - 非阻塞 connect() 和 EINTR

c++ - union 的使用定义明确了吗?

c - 为什么 stdatomic.h 包含 atomic_uint_least16_t 和 atomic_uint_fast16_t 但不包含 atomic_uint16_t?

c - alloca有什么应用?

c - 访问其指针从函数返回的结构中的二维数组时出现段错误

c - 如何使用 NULL 分配数组

ios - 使用项目模板时防止 Xcode 6.3 链接默认库和 header

c++ - 为什么 <list> 元素会在使用 malloc() 内存的对象中导致段错误

使用函数更改指针包含的地址

c++ - 为什么允许我声明一个带有已删除析构函数的对象?