c - 灵活数组成员中的严格别名?
问题描述
我正在编写一个 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 是 Nodes 的链表, Node 是一个 header,后跟 data u8 data[]
。u8 是无符号字符。我维护下一个可用索引 ( currentIndex
) 并按此索引前进data
并将其作为void *
( ptr = &a->current->data[a->currentIndex]
) 返回。这是否违反了严格的别名规则,因为我正在将指针转换u8
为其他东西并使用它?
我的困惑来自于 malloc 返回的内存没有有效类型。但是由于我将 malloc 的指针投射到并在分配它(in)之后ArenaNode *
设置它的数据成员(next
and ) ,所以有效类型变为. 或者是吗?我没有设置那个字段。 dataSize
ArenaNodeNew
ArenaNode
data
基本上,我认为问题可以简化为:如果我 malloc 内存区域的大小为 10,将指针转换为struct {int a;} *
(假设 4 个字节 int),将其设置a
为某个值,其余 6 个字节会发生什么情况?它有任何有效的类型吗?灵活数组成员的存在是否会以任何方式影响这一点?
解决方案
作为灵活数组成员一部分的额外字节在您写入它们时将具有该成员的有效类型。
您可以安全地声明ptr
为u8 *
并定义您的函数以返回该类型。
在您分配 10 个字节并将前 4 个字节视为给定类型的结构的示例中,其余字节还没有有效类型。您可以将它们用于任何类型,假设您使用的指针正确对齐,即您可以将 aint *
指向以下字节但不能指向 a long long *
。由于对齐。
推荐阅读
- c - 提交到其他页面和上一页时如何清除输入文本记录
- powershell - 创建日期等于给定日期的 Powershell 复制文件
- maven - 如何使用来自另一个 Maven 模块的宏?
- php - 从数组中创建单独的 CSV (PHP)
- linux - 如何从标准输出中获取第 13 行和倒数第二行
- javascript - 将类组件更改为功能组件:使用方法
- datatables - Tail.select 数据表
- android - 应用程序在启动时崩溃并给出空指针异常。如果用户已登录,我如何更改代码以开始下一个活动?
- django - 如何使用中间件将 http://www.example.com 重定向到 https://example.com
- c++ - 将数据保存到 .DAT 文件