C语言 为联合分配内存不足



声明如下:

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/他永远不会超过char s_char.u.c,那么分配整个sizeof(struct s1)看起来是一个很大的浪费。

另一方面,我很理解C11标准是反对这一点的——但它从来没有明确说明。我发现可以被理解为反对这一观点的两篇文章是:

  • 如果结构体以某种方式假设它的完整大小已经被分配,这打开了未定义行为的大门:一个新对象可以在s_char之后分配,但仍然在结构体假设的"实际"sizeof(struct s1)字节内,这将触发C11标准附件J.2的第54项:UB如果

对象被赋值给不完全重叠的对象或赋值给具有不兼容类型的完全重叠对象(6.5.16.1)。

  • 6.2.6.1第7段:

当一个值存储在联合类型对象的成员中时对象表示中不对应的字节数成员,但不对应于其他成员,取未指定值。

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

总之,有一种直觉是"但是我们只使用了5个字节!"而不是语言律师式的谨慎 -不证明。我的问题是:还有证据支持任何一方吗?更具体地说:是否可以为联合或任何其他数据结构分配内存不足?

再次强调:直觉是问题的根源,我不想要更多的直觉。我正在寻找一些可靠的事实推理,如C11标准和/或编译器信息。此外,我已经知道,这样做的标准方法是用带联合的结构代替具有公共初始序列的结构联合,尽管这也不是没有风险... .但这是切线

您似乎通过寻找C语言范围之外的答案而使自己感到困惑。@M。M说,这个问题并不是工会独有的。如果您没有为一个对象分配足够的内存,并且您在分配的内存之外对该对象的一部分进行写操作,那么如果之后事情变成梨形,请不要感到惊讶。

C语言允许定义指向任何已知类型的指针,甚至指向唯一"已知"属性是其名称的不完整类型。当你给这个指针赋值时,确保所提供的值是有效的,这取决于程序员。C将把指向的区域视为指针类型的对象。这对你来说很方便,可以帮助你浏览记忆。

请记住,"内存从哪里来"不在语言的范围之内。它可以来自malloc,但也可以来自sbrk(2)或mmap(2)。或者它只是一个常量,就像最初的IBM个人电脑中的视频内存缓冲区一样。如果你错误地描述了指向的东西,你不能指望编译器来拯救你。

看起来GCC维护者认为为union分配的内存不足导致了UB,正如在这个bug报告中看到的(有点间接地)。没有基于标准的解释,但这仍然意味着不能期望编译器支持它,所以进一步研究是没有意义的。

为完整起见,此缺陷报告根据CERT C安全编码规则的规则显示如下文本:

对标准内存分配函数的调用以大小为整数的参数n为参数,并假定用于类型T *,当n

负责C标准的WG14小组也参与了CSCR。

相关内容

最新更新