C++ 如何在堆栈上动态分配内存?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6335023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ How to allocate memory dynamically on stack?
提问by Mark
回答by Crashworks
Use alloca()
(sometimes called _alloca()
or _malloca()
), but be very careful about it— it frees its memory when you leave a function, not when you go out of scope, so you'll quickly blow up if you use it inside a loop.
使用alloca()
(有时称为_alloca()
or _malloca()
),但要非常小心——当你离开一个函数时它会释放它的内存,而不是当你超出范围时,所以如果你在循环中使用它,你会很快爆炸。
For example, if you have a function like
例如,如果您有一个类似的功能
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
Then the alloca() will allocate an additionalnDataSize bytes every time through the loop. None of the alloca() bytes get freed until you return from the function. So, if you have an nDataSize
of 1024 and an iterations
of 8, you'll allocate 8 kilobytes before returning. If you have an nDataSize
= 65536 and iterations
= 32768, you'll allocate a total 65536×32768=2,147,483,648 bytes, almost certainly blowing your stack and causing a crash.
然后 alloca()每次通过循环都会分配一个额外的nDataSize 字节。在您从函数返回之前,所有 alloca() 字节都不会被释放。因此,如果您有一个1024 和一个8,您将在返回之前分配 8 KB。如果您有一个= 65536 和= 32768,您将总共分配 65536×32768=2,147,483,648 字节,几乎肯定会炸毁您的堆栈并导致崩溃。nDataSize
iterations
nDataSize
iterations
anecdote:You can easily get into trouble if you write past the end of the buffer, especially if you pass the buffer into another function, and that subfunction has the wrong idea about the buffer's length. I once fixed a rather amusing bugwhere we were using alloca()
to create temporary storage for rendering a TrueType font glyph before sending it over to GPU memory. Our font library didn't account for the diacritic in the Swedish Å character when calculating glyph sizes, so it told us to allocate nbytes to store the glyph before rendering, and then actually rendered n+128 bytes. The extra 128 bytes wrote into the call stack, overwriting the return address and inducing a really painful nondeterministic crash!
轶事:如果你写越过缓冲区的末尾,你很容易遇到麻烦,特别是如果你将缓冲区传递给另一个函数,并且该子函数对缓冲区的长度有错误的想法。我曾经修复了一个相当有趣的错误,我们使用该错误alloca()
创建临时存储来渲染 TrueType 字体字形,然后再将其发送到 GPU 内存。我们的字体库在计算字形大小时没有考虑瑞典语 Å 字符中的变音符号,因此它告诉我们在渲染前分配n个字节来存储字形,然后实际渲染n+ 128 个字节。额外的 128 字节写入调用堆栈,覆盖返回地址并导致非常痛苦的非确定性崩溃!
回答by Steve Townsend
Since this is tagged C++, typically you just declare the objects you need in the correct scope. They are allocated on the stack, and guaranteed to be released on scope exit. This is RAII, and a critical advantage of C++ over C. No malloc
s or new
s, and especially no alloca
s, required.
由于这是标记为 C++,通常您只需在正确的范围内声明您需要的对象。它们在堆栈上分配,并保证在范围退出时释放。这是RAII,也是 C++ 相对于 C 的一个关键优势。不需要malloc
s 或new
s,尤其是不需要alloca
s。
回答by DuckMaestro
You can declare a local char[1024]
or whatever number of bytes you'd like (up to a point), then take the address of the local for a pointer to this block of memory on the stack. Not exactly dynamic, but you could then wrap up this memory with your own memory manager if desired.
您可以声明一个本地char[1024]
或任何您想要的字节数(最多一个点),然后获取本地地址作为指向堆栈中该内存块的指针。不完全是动态的,但是如果需要,您可以使用自己的内存管理器包装此内存。
回答by Sammy
Article discussing about dynamic memory allocation
We can allocate variable length space dynamically on stack memory by using function _alloca. This function allocates memory from the program stack. It simply takes number of bytes to be allocated and return void* to the allocated space just as malloc call. This allocated memory will be freed automatically on function exit.
So it need not to be freed explicitly. One has to keep in mind about allocation size here, as stack overflow exception may occur. Stack overflow exception handling can be used for such calls. In case of stack overflow exception one can use
_resetstkoflw()
to restore it back.So our new code with
_alloca
would be :int NewFunctionA() { char* pszLineBuffer = (char*) _alloca(1024*sizeof(char)); ….. // Program logic …. //no need to free szLineBuffer return 1; }
我们可以使用函数 _alloca 在堆栈内存上动态分配可变长度空间。该函数从程序堆栈中分配内存。它只需要分配字节数并将 void* 返回到分配的空间,就像 malloc 调用一样。这个分配的内存将在函数退出时自动释放。
所以不需要显式释放它。必须记住这里的分配大小,因为可能会发生堆栈溢出异常。堆栈溢出异常处理可用于此类调用。在堆栈溢出异常的情况下,可以使用
_resetstkoflw()
将其恢复回来。所以我们的新代码
_alloca
是:int NewFunctionA() { char* pszLineBuffer = (char*) _alloca(1024*sizeof(char)); ….. // Program logic …. //no need to free szLineBuffer return 1; }
回答by T.E.D.
When/if C++ allows the use of (non-static) const
values for array bounds, it will be easier.
当/如果 C++ 允许const
对数组边界使用(非静态)值,它会更容易。
For now, the best way I know of is via recursion. There are all kinds of clever tricks that can be done, but the easiest I know of is to have your routine declare a fixed-sized array, and fill and operate on what it has. When its done, if it needs more space to finish, it calls itself.
目前,我所知道的最好的方法是通过递归。有各种聪明的技巧可以做到,但我所知道的最简单的方法是让你的例程声明一个固定大小的数组,并填充和操作它所拥有的。完成后,如果需要更多空间来完成,它会调用自己。
回答by JDiMatteo
You could use the BDEC++ library, e.g.
您可以使用BDEC++ 库,例如
const int BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];
bdlma::BufferedSequentialAllocator allocator(buffer, BUFFER_SIZE);
bsl::vector<int> dataVector(&allocator);
dataVector.resize(50);
BDE supplies comprehensive allocator options along with collections like bsl::vector that can use polymorphic allocators without changing the type of the container.
BDE 提供全面的分配器选项以及诸如 bsl::vector 之类的集合,它们可以使用多态分配器而无需更改容器的类型。
You might also consider:
您还可以考虑: