有没有办法在stack而不是堆上分配内存?我找不到一本好书,这里有人有想法吗?
答案 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的关键优势。不需要malloc
或new
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这样的集合,可以使用多态分配器而无需更改容器的类型。
您可能还会考虑: