如何在应用程序开始时分配所有内存,然后在整个过程中相应地进行类型转换
Posted
技术标签:
【中文标题】如何在应用程序开始时分配所有内存,然后在整个过程中相应地进行类型转换【英文标题】:How to allocate all memory at beginning of app and then typecast it accordingly throughout 【发布时间】:2013-12-12 01:30:36 【问题描述】:我需要预先分配我的应用程序将使用的所有内存。然后在需要时用我需要进行计算的数据覆盖该内存。在进行任何计算之前,必须首先分配内存,因为我正在尝试并行运行多线程 CUDA 算法,正如我在此处的问题 (Multi-Threaded CPU CUDA application not asynchronous when calling CudaFree) 中所解释的那样。
我认为我可以将所需的所有内存分配为字节指针,然后将该指针存储为 void 指针:
void * allocateMemory()
byte *mem;
int nbytes = 13107200;
mem = (byte *) malloc(nbytes);
return mem;
稍后在我的程序中,我想使用已分配的内存来存储数据。我不提前知道数据的类型,但我知道它的大小不会超过分配的限制。
void doSomething(void * mem)
int *a = (int*) mem;
for (int i = 0; i < 100; i++)
a[i] = i;
//do stuff
还有许多其他函数,例如上面的 doSomething(void * mem),但它们使用 double 类型或 float 类型,甚至可能使用 byte 类型。我需要能够用我需要的任何数据类型覆盖最初分配的内存。上面的代码不起作用,因为它说我不能尊重 void 指针。它还说我试图读取或写入受保护的内存。
这样做的正确方法是什么?实现我的目标的最佳方法是在开始时分配所有内存,然后在整个过程中以必要的方式使用?谢谢!
【问题讨论】:
你正在尝试实现一个固定大小的堆。用碎片等解决这个问题并不容易。最好的办法是使用一个池,也许使用已经有这个的 boost。 刚刚看到你的另一个问题,我认为你误解了答案。他说的是做 malloc, loop, free, not begin loop, malloc, free, end loop。 我过去做过类似的事情,其中对象或多或少地永久分配在连续的存储区域中。如果您不需要解除分配/重用,则相当容易。如果您希望能够解除分配/重用,那么您正在实现自己的堆(为此我推荐使用笛卡尔树)。 (不过,至少,您需要维护一个“下一个”指针来分配下一个字节,并且可能还需要一个“最大”指针/长度来告诉您何时分配破坏了你的分配。) 你在上面展示的可能不是最干净、最聪明的方法,但它应该可以工作。我怀疑你的问题出在其他地方。 【参考方案1】:听起来你有两个问题。
无法取消引用 void 指针。在您的代码中的某处,您使用了来自allocateMemory()
的结果而没有进行强制转换。您提供的代码是可以的,但是编译器标记为错误的任何行都不行。例如,也许你有:
void *foo = allocateMemory();
foo[42]; // compiler doesn't have a real type here - error
((int*)foo)[42]; // compiler happy
试图访问受保护的内存。在您的代码中的某处,您有一个无效的指针。最可能的原因是 allocateMemory()
返回 NULL(您没有检查它)。
您的一般方法对我来说似乎没问题;您描述的问题与代码中的细节有关,而不是整体想法。
【讨论】:
哇,我觉得自己很笨。大声笑我梳理了我的代码,发现这是一个复制粘贴错误。我将 ptr1、ptr2、ptr3 和 ptr4 设置为 allocateMemory()。我不小心做了两次ptr2,所以ptr3从来没有分配过内存。我猜这在尝试使用 ptr3 时会导致访问受保护的内存问题。我不确定为什么我有取消引用空指针问题,但是在修复了先前的错误并在这里和那里清理我的代码之后,我不再有任何错误。谢谢!以上是关于如何在应用程序开始时分配所有内存,然后在整个过程中相应地进行类型转换的主要内容,如果未能解决你的问题,请参考以下文章