Я пишу Arena Allocator, и он работает, но я чувствую, что он нарушает строгие правила наложения имен.Я хочу знать, прав я или нет.Вот соответствующая часть кода:
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;
}
Arena - это связанный список узлов, а узел - это заголовок, за которым следуют данные u8 data[]
.u8 - беззнаковый символЯ поддерживаю следующий доступный индекс (currentIndex
) и продвигаюсь на data
по этому индексу и возвращаю его как void *
(ptr = &a->current->data[a->currentIndex]
).Это нарушает строгое правило алиасинга, потому что я конвертирую указатель на u8
на что-то другое и использую это?
Мое замешательство связано с тем, что память, возвращаемая malloc, не имеет эффективного типа.Но так как я приведу указатель malloc к ArenaNode *
и задаю его элементы данных (next
и dataSize
) после его выделения (в ArenaNodeNew
), эффективный тип становится ArenaNode
.Или это?Я не установил data
поле этого.
В принципе, я думаю, что вопрос можно упростить до следующего: если я выделю область памяти, скажем, размером 10, приведу указатель к struct {int a;} *
(предположим, 4 байта int), установите для a
значениечто-то, что происходит с остальными 6 байтами?Есть ли у него эффективный тип?Влияет ли присутствие гибкого члена массива на это каким-либо образом?