Skip to content

UB59

definition⚓︎

An attempt is made to access, or generate a pointer to just past, a flexible array member of a structure when the referenced object provides no elements for that array .

description⚓︎

As a special case, the last member of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.

作为一种特殊情况,具有多个命名成员的结构体的最后一个成员可以是不完整的数组类型,称之为灵活数组成员。在大多数情况下,灵活的数组成员会被忽略,结构的大小就好像忽略了灵活数组成员被省略。然而,当灵活数组成员被调用,它表现得好像被对应类型的最长数组取代(确保不会超出内存限制)。如果这个数组没有元素,表现得就像有一个元素,但如果试图访问该元素或通过该元素生成一个指针,则行为是未定义的。

就下面的例子来讲,struct A 有两个命名成员,其中 d 是上文所提到的灵活数组成员,需要在初始化时设定足够的空间(例如malloc),此处仅给定6字节不足以存放一个double类型,此时针对灵活数组成员 d 的访问或修改都是 undefined behavior 。

code⚓︎

#include<stdio.h>
#include<stdlib.h>

struct A {
    int n;
    double d[];
}*a;

int main() {
    a = (struct A*)malloc(sizeof(struct A) + 6);
    double *d = &(a->d[0]);
    *d = 5; //undefined behavior
}