C ++如何在堆栈上动态分配内存?

时间:2011-06-13 19:08:53

标签: c++ memory memory-management

有没有办法在stack而不是堆上分配内存?我找不到一本好书,这里有人有想法吗?

7 个答案:

答案 0 :(得分:38)

使用alloca()(有时称为_alloca()_malloca()),但是be very careful about it - 它会在您离开某个功能时释放其内存,而不是在您超出范围时,如果你在循环中使用它,你会很快爆炸。

例如,如果你有像

这样的功能
int foo( int nDataSize, int iterations ) 
{
   for ( int i = 0; i < iterations ; ++i )
   {
      char *bytes = alloca( nDataSize );
      // the memory above IS NOT FREED when we pass the brace below!
   } 
   return 0;
}  // alloca() memory only gets freed here

然后,alloca()将每次通过循环分配附加 nDataSize字节。在从函数返回之前,所有alloca()字节都不会被释放。因此,如果您的nDataSize为1024,iterations为8,则在返回之前将分配8千字节。如果您有nDataSize = 65536且iterations = 32768,则您将分配总计65536×32768 = 2,147,483,648字节,几乎可以肯定会导致堆栈崩溃并导致崩溃。

轶事:如果你写过缓冲区的末尾,特别是如果你将缓冲区传递给另一个函数,那么你很容易遇到麻烦,而且这个子函数对缓冲区的长度有错误的想法。 I once fixed a rather amusing bug我们使用alloca()创建临时存储来呈现TrueType字体字形,然后再将其发送到GPU内存。我们的字体库在计算字形大小时没有考虑瑞典Å字符中的变音符号,所以它告诉我们在渲染之前分配 n 字节来存储字形,然后实际呈现 n +128个字节。额外的128个字节写入调用堆栈,覆盖返回地址并引发一个非常痛苦的不确定性崩溃!

答案 1 :(得分:5)

由于这是标记的C ++,通常只需在正确的范围内声明所需的对象。它们在堆栈上分配,并保证在范围退出时释放。这是RAII,是C ++相对于C的关键优势。不需要mallocnew s,特别是没有alloca s。

答案 2 :(得分:3)

你可以声明一个本地char[1024]或你想要的任何数量的字节(直到一个点),然后取本地的地址作为指向堆栈上这个内存块的指针。不完全是动态的,但如果需要,你可以用你自己的内存管理器包装这个内存。

答案 3 :(得分:2)

Article discussing about dynamic memory allocation

  

我们可以在堆栈内存上动态分配可变长度空间   使用功能   _alloca。此函数从程序堆栈分配内存。它只需要分配字节数并返回void *   像malloc调用一样分配空间。这个分配的内存将是   在功能退出时自动释放。

     

所以不需要明确释放它。人们必须牢记   这里的分配大小,因为可能发生堆栈溢出异常。堆   溢出异常处理可用于此类调用。的情况下   堆栈溢出异常可以使用_resetstkoflw()来恢复它   回来。

     

因此我们使用_alloca的新代码将是:

int NewFunctionA()
{
   char* pszLineBuffer = (char*) _alloca(1024*sizeof(char));
    …..
  // Program logic
     ….
  //no need to free szLineBuffer
  return 1;
}

答案 4 :(得分:1)

请参阅_malloca(http://msdn.microsoft.com/en-us/library/5471dc8s(v = VS.100).aspx)。

答案 5 :(得分:1)

当/如果C ++允许对数组边界使用(非静态)const值时,它将更容易。

目前,我所知道的最好方法是通过递归。有各种各样的聪明技巧可以做,但我知道的最简单的方法是让你的例程声明一个固定大小的数组,并填充和操作它的内容。完成后,如果需要更多空间来完成,它就会自行调用。

答案 6 :(得分:1)

您可以使用BDE C ++库,例如

const int BUFFER_SIZE = 1024;
char      buffer[BUFFER_SIZE];

bdlma::BufferedSequentialAllocator allocator(buffer, BUFFER_SIZE);
bsl::vector<int>                   dataVector(&allocator);

dataVector.resize(50);

BDE提供全面的分配器选项以及像bsl :: vector这样的集合,可以使用多态分配器而无需更改容器的类型。

您可能还会考虑: