本文介绍了哪些对齐问题限制了malloc创建的内存块的使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个用C语言进行各种数学计算的库.其中一些需要一些临时"空间-用于中间计算的内存.所需空间取决于输入的大小,因此无法静态分配.通常,该库将用于使用相同大小的输入执行许多相同类型的计算的迭代,因此,我不希望每次调用时都不要在库中使用mallocfree;一次分配足够大的块,然后将其重新用于所有计算,然后释放它,效率会更高.

I am writing a library for various mathematical computations in C. Several of these need some "scratch" space -- memory that is used for intermediate calculations. The space required depends on the size of the inputs, so it cannot be statically allocated. The library will typically be used to perform many iterations of the same type of calculation with the same size inputs, so I'd prefer not to malloc and free inside the library for each call; it would be much more efficient to allocate a large enough block once, re-use it for all the calculations, then free it.

我的预期策略是请求void指向单个内存块的指针,也许带有随附的分配函数.说,像这样:

My intended strategy is to request a void pointer to a single block of memory, perhaps with an accompanying allocation function. Say, something like this:

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

这个想法是,如果用户打算进行多个相同大小的计算,则他可以使用分配函数来抓取一个足够大的块,然后使用该相同的内存块为每个内存块执行计算.输入.分配功能不是严格必需的,但是它简化了界面,并使得将来更改存储要求变得更加容易,而无需每个库用户都确切知道需要多少空间.

The idea is that if the user intends to do several calculations of the same size, he may use the allocate function to grab a block that is large enough, then use that same block of memory to perform the calculation for each of the inputs. The allocate function is not strictly necessary, but it simplifies the interface and makes it easier to change the storage requirements in the future, without each user of the library needing to know exactly how much space is required.

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

In many cases, the block of memory I need is just a large array of type double, no problems there. But in some cases I need mixed data types -- say a block of doubles AND a block of integers. My code needs to be portable and should conform to the ANSI standard. I know that it is OK to cast a void pointer to any other pointer type, but I'm concerned about alignment issues if I try to use the same block for two types.

因此,一个具体的例子.假设我需要3个c5和5个c6的块.我可以像这样实现我的功能吗?

So, specific example. Say I need a block of 3 doubles and 5 ints. Can I implement my functions like this:

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块,然后再使用double块,那将会改变double的对齐方式(假定为64位)双打和32位整数).有一个更好的方法吗?还是我应该考虑的更标准的方法?

Is this legal? The alignment probably works out OK in this example, but what if I switch it around and take the int block first and the double block second, that will shift the alignment of the double's (assuming 64-bit doubles and 32-bit ints). Is there a better way to do this? Or a more standard approach I should consider?

我的最大目标如下:

  • 如果可能的话,我想使用一个块,这样用户就不必处理多个块或需要改变数目的块.
  • 我希望该块是malloc获得的有效块,因此用户可以在完成后调用free.这意味着我不想做一些事情,例如创建一个小的struct,它具有指向每个块的指针,然后分别分配每个块,这将需要一个特殊的destroy函数.如果这是唯一"的方式,我愿意这样做.
  • 算法和内存要求可能会发生变化,因此我试图使用分配功能,以便将来的版本可以为潜在的不同类型的数据获得不同数量的内存,而不会破坏向后兼容性.
  • I'd like to use a single block if possible so the user doesn't have to deal with multiple blocks or a changing number of blocks required.
  • I'd like the block to be a valid block obtained by malloc so the user can call free when finished. This means I don't want to do something like creating a small struct that has pointers to each block and then allocating each block separately, which would require a special destroy function; I'm willing to do that if that's the "only" way.
  • The algorithms and memory requirements may change, so I'm trying to use the allocate function so that future versions can get different amounts of memory for potentially different types of data without breaking backward compatibility.

也许此问题已在C标准中解决,但我找不到它.

Maybe this issue is addressed in the C standard, but I haven't been able to find it.

推荐答案

如果用户正在调用您的库的分配函数,那么他们应该调用您的库的释放函数.这是非常典型的(也是很好的)界面设计.

If the user is calling your library's allocation function, then they should call your library's freeing function. This is very typical (and good) interface design.

所以我要说的只是针对不同类型的指向不同池的指针的结构.那是干净,简单和可移植的,任何阅读您的代码的人都将确切地了解您的工作.

So I would say just go with the struct of pointers to different pools for your different types. That's clean, simple, and portable, and anybody who reads your code will see exactly what you are up to.

如果您不介意浪费内存并坚持使用单个块,则可以创建具有所有类型的联合,然后分配这些类型的数组...

If you do not mind wasting memory and insist on a single block, you could create a union with all of your types and then allocate an array of those...

试图在大块中找到适当对齐的内存只是一团糟.我什至不确定您是否可以随身携带它.有什么计划?将指针转换为intptr_t,进行四舍五入,然后再转换回指针?

Trying to find appropriately aligned memory in a massive block is just a mess. I am not even sure you can do it portably. What's the plan? Cast pointers to intptr_t, do some rounding, then cast back to a pointer?

这篇关于哪些对齐问题限制了malloc创建的内存块的使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 09:03