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

问题描述 投票:0回答:7

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

c++ memory memory-management
7个回答
62
投票

使用

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

然后

alloca()
每次循环都会分配一个额外的nDataSize字节。在从函数返回之前,所有 alloca() 字节都不会被释放。因此,如果您的
nDataSize
为 1024,
iterations
为 8,则返回前将分配 8 KB。如果你有
nDataSize = 65536
iterations = 32768
,你将总共分配 65536×32768=2,147,483,648 字节,几乎肯定会破坏你的堆栈并导致崩溃。

轶事:

如果您写入的内容超出了缓冲区的末尾,特别是如果您将缓冲区传递给另一个函数,并且该子函数对缓冲区的长度有错误的想法,那么您很容易陷入麻烦。 我曾经修复了一个相当有趣的错误,我们使用 alloca() 创建临时存储来渲染 TrueType 字体字形,然后再将其发送到 GPU 内存。我们的字体库在计算字形大小时没有考虑瑞典语 Å 字符中的变音符号,因此它告诉我们在渲染之前分配

n
字节来存储字形,然后实际渲染
n+128
字节。额外的 128 字节写入调用堆栈,覆盖返回地址并引发非常痛苦的不确定性崩溃!
    


9
投票
RAII

,也是 C++ 相对于 C 的关键优势。不需要 malloc

new
,尤其是不需要
alloca
    


3
投票
char[1024]

或您想要的任何字节数(在一定程度上),然后获取本地地址作为指向堆栈上该内存块的指针。不完全是动态的,但如果需要,您可以使用自己的内存管理器包装该内存。

    


3
投票
讨论动态内存分配的文章

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

所以不需要显式释放它。人们必须牢记 这里分配大小,因为可能会发生堆栈溢出异常。堆 溢出异常处理可用于此类调用。的情况下 堆栈溢出异常可以使用

_resetstkoflw()

来恢复 回来了。

  
  
所以我们带有

_alloca

的新代码将是:


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

    

3
投票

_malloca


0
投票
const

值作为数组边界,这会更容易。


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


0
投票
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 等集合,可以使用多态分配器而无需更改容器的类型。

您也可以考虑:

    https://github.com/facebook/folly/blob/master/folly/docs/small_vector.md
  • http://www.boost.org/doc/libs/1_55_0/doc/html/container/non_standard_containers.html#container.non_standard_containers.static_vector
  • http://llvm.org/docs/doxygen/html/classllvm_1_1SmallVector.html
© www.soinside.com 2019 - 2024. All rights reserved.