简体   繁体   English

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

[英]C++ How to allocate memory dynamically on stack?

Is there a way to allocate memory on stack instead of heap?有没有办法在堆栈而不是堆上分配 memory? I can't find a good book on this, anyone here got an idea?我找不到这方面的好书,这里有人知道吗?

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. Use alloca() (sometimes called _alloca() or _malloca( _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在循环中使用它。

For example, if you have a function like例如,如果你有一个 function 像

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 additional nDataSize bytes every time through the loop .然后 alloca() 将在每次循环时分配一个额外的 nDataSize 字节。 None of the alloca() bytes get freed until you return from the function.在您从 function 返回之前,不会释放 alloca() 字节。 So, if you have an nDataSize of 1024 and an iterations of 8, you'll allocate 8 kilobytes before returning.因此,如果您的nDataSize为 1024 且iterations为 8,您将在返回之前分配 8 KB。 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.如果你有一个nDataSize = 65536 和iterations = 32768,你将分配总共 65536×32768=2,147,483,648 字节,几乎肯定会炸毁你的堆栈并导致崩溃。

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.轶事:如果你写超过缓冲区的末尾,你很容易遇到麻烦,特别是如果你将缓冲区传递到另一个 function,并且该子函数对缓冲区的长度有错误的想法。 I once fixed a rather amusing bug where we were using alloca() to create temporary storage for rendering a TrueType font glyph before sending it over to GPU memory. 我曾经修复了一个相当有趣的错误,我们使用alloca()创建临时存储以渲染 TrueType 字体字形,然后将其发送到 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 n bytes to store the glyph before rendering, and then actually rendered n +128 bytes.我们的字体库在计算字形大小时没有考虑瑞典 Å 字符中的变音符号,所以它告诉我们在渲染之前分配n个字节来存储字形,然后实际渲染n +128 个字节。 The extra 128 bytes wrote into the call stack, overwriting the return address and inducing a really painful nondeterministic crash!额外的 128 字节写入调用堆栈,覆盖了返回地址并引发了非常痛苦的非确定性崩溃!

Since this is tagged C++, typically you just declare the objects you need in the correct scope.由于这被标记为 C++,通常您只需在正确的 scope 中声明您需要的对象。 They are allocated on the stack, and guaranteed to be released on scope exit.它们在堆栈上分配,并保证在 scope 退出时释放。 This is RAII , and a critical advantage of C++ over C.这是RAII ,也是 C++ 优于 C 的关键优势。 No malloc s or new s, and especially no alloca s, required.不需要mallocnew ,尤其是不需要alloca

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.您可以声明一个本地char[1024]或任何您想要的字节数(最多),然后将本地地址作为指向堆栈上 memory 块的指针。 Not exactly dynamic, but you could then wrap up this memory with your own memory manager if desired.不完全是动态的,但是如果需要,您可以使用自己的 memory 管理器来包装这个 memory。

Article discussing about dynamic memory allocation 讨论动态memory分配的文章

We can allocate variable length space dynamically on stack memory by using function _alloca.我们可以使用 function _alloca 在堆栈 memory 上动态分配可变长度空间。 This function allocates memory from the program stack.这个 function 从程序堆栈中分配 memory。 It simply takes number of bytes to be allocated and return void* to the allocated space just as malloc call.它只需要分配字节数并将 void* 返回到分配的空间,就像 malloc 调用一样。 This allocated memory will be freed automatically on function exit.这个分配的 memory 将在 function 退出时自动释放。

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.如果发生堆栈溢出异常,可以使用_resetstkoflw()将其恢复。

So our new code with _alloca would be:因此,我们使用_alloca的新代码将是:

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

You could use the BDE C++ library, eg您可以使用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 supplies comprehensive allocator options along with collections like bsl::vector that can use polymorphic allocators without changing the type of the container. BDE 提供全面的分配器选项以及 collections 等 bsl::vector 可以使用多态分配器而无需更改容器的类型。

You might also consider:您还可以考虑:

See _malloca . _malloca

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.完成后,如果需要更多空间来完成,它会调用自身。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM