首页 > 解决方案 > 分配连续内存以包含具有灵活数组成员的多个结构

问题描述

考虑一个包含灵活数组成员的结构,如下所示:

typedef struct {
    size_t len;
    char data[];
} Foo;

我有一个未知数量的 Foo,每个都是未知大小,但是我可以确定我所有的 Foo 加起来正好是 1024 字节。如何在知道每个 Foo 的长度之前为一个 Foos 数组分配 1024 个字节,然后再填充该数组的成员?

像这样的东西,虽然它抛出了一个段错误:

Foo *array = malloc(1024);
int array_size = 0;

Foo foo1;
strcpy(foo1.data, "bar");
array[0] = foo1;
array_size++;

Foo foo2;
strcpy(foo2.data, "bar");
array[1] = foo2;
array_size++;

for (int i = 0; i < array_size; i++)
    puts(array[i].data);

想要这样做的原因是将所有 Foos 保持在一个连续的内存区域中,以便 CPU 缓存友好。

标签: cmemoryflexible-array-member

解决方案


根本不能有一个 foos 数组,因为 foo 没有固定的大小,并且数组的定义特征是每个对象都有固定的大小和从其索引的基本可计算偏移量。对于您想要工作的内容,索引array[n]必须知道foo[0], foo[1], ...,的完整大小foo[n-1],这是不可能的,因为语言不知道这些大小;在实践中,灵活的数组成员只是被排除在大小之外,因此将与's 的数据foo[1]“重叠” 。foo[0]

如果您需要能够以数组的形式访问这些对象,则需要放弃在每个对象中放置一个灵活的数组成员。相反,您可以将所有数据放在最后,并在每个数据中存储指向数据的指针或偏移量。如果您不需要能够将它们作为数组访问,则可以改为在分配的内存中构建一种链表,将下一个条目的偏移量存储为每个条目的成员。(例如,参见如何struct direntgetdents大多数 Unices 上使用。)


推荐阅读