有没有办法在stack而不是堆上分配内存?我找不到这方面的好书,这里有人有想法吗?
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 字节写入调用堆栈,覆盖返回地址并引发非常痛苦的不确定性崩溃!char[1024]
或您想要的任何字节数(在一定程度上),然后获取本地地址作为指向堆栈上该内存块的指针。不完全是动态的,但如果需要,您可以使用自己的内存管理器包装该内存。
所以不需要显式释放它。人们必须牢记 这里分配大小,因为可能会发生堆栈溢出异常。堆 溢出异常处理可用于此类调用。的情况下 堆栈溢出异常可以使用
_resetstkoflw()
来恢复 回来了。
所以我们带有_alloca
的新代码将是:
int NewFunctionA() { char* pszLineBuffer = (char*) _alloca(1024*sizeof(char)); ….. // Program logic …. //no need to free szLineBuffer return 1; }
const
值作为数组边界,这会更容易。
目前,我所知道的最好的方法是通过递归。有各种各样的巧妙技巧可以完成,但我知道的最简单的技巧是让您的例程声明一个固定大小的数组,然后填充并对其进行操作。完成后,如果需要更多空间来完成,它会调用自身。