gpt4 book ai didi

c - 哪些对齐问题限制了 malloc 创建的内存块的使用?

转载 作者:太空狗 更新时间:2023-10-29 17:21:24 25 4
gpt4 key购买 nike

我正在用 C 编写一个用于各种数学计算的库。其中一些需要一些“暂存”空间——用于中间计算的内存。所需空间取决于输入的大小,因此不能静态分配。该库通常用于使用相同大小的输入执行相同类型计算的多次迭代,因此我不希望在库中使用 mallocfree每次通话;一次分配一个足够大的 block ,将其重新用于所有计算,然后释放它会更有效率。

我打算采用的策略是请求一个指向单个内存块的 void 指针,也许还有一个伴随的分配函数。比如说,像这样:

void *allocateScratch(size_t rows, size_t columns);
void doCalculation(size_t rows, size_t columns, double *data, void *scratch);

这个想法是,如果用户打算进行多个相同大小的计算,他可以使用分配函数来获取足够大的 block ,然后使用同一 block 内存为每个计算执行计算输入。 allocate 函数并不是绝对必要的,但它简化了界面并使将来更改存储要求变得更加容易,图书馆的每个用户都不需要确切地知道需要多少空间。

在很多情况下,我需要的内存块只是一个double类型的大数组,没有问题。但在某些情况下,我需要混合数据类型——比如一个 double block 和一个整数 block 。我的代码需要可移植并且应该符合 ANSI 标准。我知道可以将 void 指针转换为任何其他指针类型,但如果我尝试对两种类型使用相同的 block ,我会担心对齐问题。

所以,具体的例子。假设我需要一个包含 3 个 double 和 5 个 int 的 block 。我可以像这样实现我的功能吗:

void *allocateScratch(...) {
return malloc(3 * sizeof(double) + 5 * sizeof(int));
}

void doCalculation(..., void *scratch) {
double *dblArray = scratch;
int *intArray = ((unsigned char*)scratch) + 3 * sizeof(double);
}

这合法吗?在这个例子中对齐可能没问题,但是如果我把它调过来,首先使用 int block ,然后使用 double block ,那将会改变double(假设 64 位 double 和 32 位整数)。有一个更好的方法吗?或者我应该考虑更标准的方法?

我最大的目标如下:

  • 如果可能,我想使用单个 block ,这样用户就不必处理多个 block 或所需 block 数的变化。
  • 我希望该 block 是通过 malloc 获得的有效 block ,以便用户可以在完成后调用 free。这意味着我不想做一些事情,比如创建一个小的 struct ,它有指向每个 block 的指针,然后分别分配每个 block ,这需要一个特殊的 destroy 函数;如果那是“唯一”的方式,我愿意这样做。
  • 算法和内存要求可能会发生变化,因此我正在尝试使用分配函数,以便 future 版本可以为可能不同类型的数据获得不同数量的内存,而不会破坏向后兼容性。

也许这个问题在 C 标准中已经解决,但我没能找到它。

最佳答案

单个 malloc 的内存可以分区以用于多个数组,如下所示。

假设我们想要具有 NA、NB 和 NC 元素的类型 A、B 和 C 的数组。我们这样做:

size_t Offset = 0;

ptrdiff_t OffsetA = Offset; // Put array at current offset.
Offset += NA * sizeof(A); // Move offset to end of array.

Offset = RoundUp(Offset, sizeof(B)); // Align sufficiently for type.
ptrdiff_t OffsetB = Offset; // Put array at current offset.
Offset += NB * sizeof(B); // Move offset to end of array.

Offset = RoundUp(Offset, sizeof(C)); // Align sufficiently for type.
ptrdiff_t OffsetC = Offset; // Put array at current offset.
Offset += NC * sizeof(C); // Move offset to end of array.

unsigned char *Memory = malloc(Offset); // Allocate memory.

// Set pointers for arrays.
A *pA = Memory + OffsetA;
B *pB = Memory + OffsetB;
C *pC = Memory + OffsetC;

RoundUp 是:

// Return Offset rounded up to a multiple of Size.
size_t RoundUp(size_t Offset, size_t Size)
{
size_t x = Offset + Size - 1;
return x - x % Size;
}

这使用事实,如noted by R.. ,类型的大小必须是该类型对齐要求的倍数。在 C 2011 中,RoundUp 调用中的 sizeof 可以更改为 _Alignof,这可以在对齐要求时节省少量空间类型小于其大小。

关于c - 哪些对齐问题限制了 malloc 创建的内存块的使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21130410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com