C-柔性阵列成员严格的混叠



我正在写一个竞技场分配器,它有效,但我觉得它违反了严格的混叠规则。我想知道我是对还是错。这是代码的相关部分:

typedef struct ArenaNode ArenaNode;
struct ArenaNode {
    ArenaNode *next;
    size_t dataSize;
    u8 data[];
};
typedef struct {
    ArenaNode *head;
    ArenaNode *current;
    size_t currentIndex;
} Arena;
static ArenaNode *ArenaNodeNew(size_t dataSize, ArenaNode *next)
{
    ArenaNode *n = malloc(sizeof(ArenaNode) + dataSize);
    n->next = NULL;
    n->dataSize = dataSize;
    return n;
}
void *ArenaAlloc(Arena *a, size_t size)
{
    const size_t maxAlign = alignof(max_align_t);
    size_t offset = nextHigherMultiplePow2(offsetof(ArenaNode, data), maxAlign) - offsetof(ArenaNode, data);
    size_t dataSize = offset + max(size, ARENA_SIZE);
    // first time
    void *ptr;
    if (a->head == NULL) {
        ArenaNode *n = ArenaNodeNew(dataSize, NULL);
        a->head = n;
        a->current = n;
        ptr = n->data + offset;
        a->currentIndex = nextHigherMultiplePow2(offset + size, maxAlign);
    } else {
        // enough space
        if (a->currentIndex + size <= a->current->dataSize) {
            ptr = &a->current->data[a->currentIndex];
            a->currentIndex = nextHigherMultiplePow2(a->currentIndex + size, maxAlign);
        } else {
            ArenaNode *n = ArenaNodeNew(dataSize, NULL);
            a->current->next = n;
            a->current = n;
            ptr = n->data + offset;
            a->currentIndex = nextHigherMultiplePow2(offset + size, maxAlign);
        }
    }
    return ptr;
}

竞技场是节点的链接列表,节点是标头,然后是数据u8 data[]。U8是未签名的字符。我维护下一个可用索引(currentIndex),并通过此索引提前data,并将其返回为void *ptr = &a->current->data[a->currentIndex])。这是否违反了严格的混叠规则,因为我将指针转换为u8并使用它?

我的混乱来自于Malloc返回的记忆没有有效类型的事实。但是,由于我将malloc'd指针投入到ArenaNode *并在分配后设置其数据成员(nextdataSize)(在ArenaNodeNew中),因此有效类型变为ArenaNode。还是这样?我没有设置其中的data字段。

基本上,我认为可以简化这个问题:如果我malloc malloc as says says,size 10,将指针施放为struct {int a;} *(假设4字节INT),将其设置为a,将其设置为某物在6个字节中?它有任何有效类型吗?柔性阵列成员的存在是否以任何方式影响它?

在您写信给他们时,是灵活数组成员的一部分的额外字节将具有该成员的有效类型。

您可以安全地将ptr声明为u8 *并定义您的功能以返回该类型。

在您分配10个字节并将前4个视为给定类型的结构的示例中,其余字节还没有有效类型。您可以将它们用于任何类型,假设您使用的指针正确对齐,即,您可以将int *指向以下字节,而不是long long *。由于对齐。

这是否违反了严格的混溶规则,因为我将指针转换为u8并使用它?

否,您没有违反严格的别名,但是您的代码可能会违反 7.22.3内存管理功能,第1段:

施加的约束。

如果分配成功是适当对齐的,则返回的指针可以将其分配给具有基本对齐要求的任何类型的对象的指针,然后用于访问分配的空间中的对象或此类对象...

您似乎并没有确保使用任何对象的内存是"适当对齐"的。对于任何对象。给定 6.3.2.3指针,第7段的语句:

指向对象类型的指针可以转换为指针转换为其他对象类型。如果结果指针未正确对齐引用类型,则该行为是不确定的。

您似乎冒着不确定的行为的风险。

"适当对齐"是非常取决于平台的。

最新更新