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

Mar*_*ark 35 c++ memory memory-management

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

Cra*_*rks 43

使用alloca()(有时称为_alloca()_malloca()),但要非常小心 - 当你离开一个函数时,它会释放它的内存,而不是当你超出范围时,如果你在循环中使用它,你会很快爆炸.

例如,如果你有一个像这样的功能

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
Run Code Online (Sandbox Code Playgroud)

然后alloca()将每次循环分配一个额外的 nDataSize字节.在从函数返回之前,所有alloca()字节都不会被释放.因此,如果你有一个1024和一个8,你将在返回之前分配8千字节.如果你有一个= 65536和= 32768,你将分配总计65536×32768 = 2,147,483,648字节,几乎肯定会炸毁你的堆栈并导致崩溃.nDataSizeiterationsnDataSizeiterations

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

  • @Neil Butterworth我们在嵌入式开发中实际上没有使用标准C++的原因之一.= P (16认同)
  • @Mark:好吧,停下来思考一下.什么是alloca(),以及函数的返回类型如何影响它? (4认同)
  • @Crashworks 链接已损坏,我想了解您的错误! (4认同)

Ste*_*end 6

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

  • 这里的问题是许多C++对象为自己分配内存. (2认同)
  • 您可以调用填充向量的函数.您可能需要一个字符串.您可能需要这些东西非常快且线程安全.如果你不需要这些东西超出功能,那么堆栈存储就是正确的地方. (2认同)